Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with self when inheriting generic traits. #4183

Closed
brendanzab opened this issue Dec 14, 2012 · 14 comments
Closed

Problem with self when inheriting generic traits. #4183

brendanzab opened this issue Dec 14, 2012 · 14 comments
Assignees
Labels
A-trait-system Area: Trait system

Comments

@brendanzab
Copy link
Member

extern mod std;
use std::cmp::FuzzyEq;

trait Float: FuzzyEq<Self> {
    static pure fn two_pi() -> Self;
}

impl f32: Float {
    static pure fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 }
}

struct Radians<T>(T);

impl<T:Copy Float> Radians<T> {
    static pure fn full_turn() -> Radians<T> { Radians(Float::two_pi())    }
}

fn main() {}
src/float.rs:16:55: 16:68 error: mismatched types: expected `@FuzzyEq<'a>` but found `@FuzzyEq<self>` (expected type parameter but found self)
src/float.rs:16     static pure fn full_turn() -> Radians<T> { Radians(Float::two_pi())    }
                                                                       ^~~~~~~~~~~~~
error: aborting due to previous error

Update: changed to capitalized Self
Update: Use FuzzyEq trait from std::cmp

@brendanzab
Copy link
Member Author

If this can be fixed this would allow us define Num with trait constraints from ops::core. ie:

trait Num: Add<self,self>
           Sub<self,self>
           Mul<self,self>
           Div<self,self>
           Modulo<self,self>
           Neg<self>
           Ord Eq { ... }

@brendanzab
Copy link
Member Author

@catamorphism (nag nag)

@brendanzab
Copy link
Member Author

I did a search for "mismatched types: expecting", and it seems to be pointing to librustc/middle/typeck/check/_match.rs. Dunno if that's of any help.

@brendanzab
Copy link
Member Author

There also seems to be one at librustc/middle/typeck/check/mod.rs

    fn report_mismatched_types(sp: span, e: ty::t, a: ty::t,
                               err: &ty::type_err) {
        // Don't report an error if expected is ty_err
        let resolved_expected =
            self.resolve_type_vars_if_possible(e);
        let mk_msg = match ty::get(resolved_expected).sty {
            ty::ty_err => return,
            _ => {
                // if I leave out : ~str, it infers &str and complains
                |actual: ~str| {
                    fmt!("mismatched types: expected `%s` but found `%s`",
                         self.ty_to_str(resolved_expected), actual)
                }
            }
        };
        self.type_error_message(sp, mk_msg, a, Some(err));
    }

@catamorphism
Copy link
Contributor

I think this is failing because typeck isn't applying substs properly when checking the inherited trait. If I comment out the : FuzzyEq<Self>, it compiles. Investigating more.

@brendanzab
Copy link
Member Author

Cheers, the help is most appreciated.

@catamorphism
Copy link
Contributor

So far I've figured out that the self type doesn't get substituted correctly when checking the inherited trait, but simplistically applying the substs from the self type (T as bound by the Radians impl in this case) doesn't work either. Basically, the typechecker says "self isn't T" because the knowledge that T gets instantiated with self here gets lost somewhere.

I don't understand the code well enough to know what to do, though; still digging.

@catamorphism
Copy link
Contributor

After talking to @nikomatsakis , I think this will be easier to fix after fixing #4678, so I'm going to consider this blocked on #4678.

@brendanzab
Copy link
Member Author

Referencing this pull: #4910

@nikomatsakis
Copy link
Contributor

I am doing some refactoring so as to make object types and the rest sound and correctly implemented. This is needed to prepare for my rewritten and expanded borrow checker. I have a feeling this refactoring will solve this issue, or at least make it much clearer what's going on.

@catamorphism
Copy link
Contributor

Not critical for 0.6; de-milestoning.

@ghost ghost assigned nikomatsakis Mar 27, 2013
nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Apr 4, 2013
…e with a

bare function store (which is not in fact a kind of value) but rather
ty::TraitRef.  Removes many uses of fail!() and other telltale signs of
type-semantic mismatch.

cc rust-lang#4183 (not a fix, but related)
nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Apr 5, 2013
…e with a

bare function store (which is not in fact a kind of value) but rather
ty::TraitRef.  Removes many uses of fail!() and other telltale signs of
type-semantic mismatch.

cc rust-lang#4183 (not a fix, but related)
bors added a commit that referenced this issue Apr 6, 2013
…atsakis

These are a number of incremental steps towards #4183 and #4646.
@nikomatsakis
Copy link
Contributor

Just a progress report: I've got the fix for this almost done...a couple of tests failing though so not quite there.

@brendanzab
Copy link
Member Author

  • claps hands excitedly *

nikomatsakis added a commit to nikomatsakis/rust that referenced this issue Apr 9, 2013
…mber of ways.

- In a TraitRef, use the self type consistently to refer to the Self type:
  - trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
  - trait ref in `A:Trait` has the self type `A`
  - trait ref associated with a trait decl has self type `Self`
  - trait ref associated with a supertype has self type `Self`
  - trait ref in an object type `@Trait` has no self type

- Rewrite `each_bound_traits_and_supertraits` to perform
  substitutions as it goes, and thus yield a series of trait refs
  that are always in the same 'namespace' as the type parameter
  bound given as input.  Before, we left this to the caller, but
  this doesn't work because the caller lacks adequare information
  to perform the type substitutions correctly.

- For provided methods, substitute the generics involved in the provided
  method correctly.

- Introduce TypeParameterDef, which tracks the bounds declared on a type
  parameter and brings them together with the def_id and (in the future)
  other information (maybe even the parameter's name!).

- Introduce Subst trait, which helps to cleanup a lot of the
  repetitive code involved with doing type substitution.

- Introduce Repr trait, which makes debug printouts far more convenient.

Fixes rust-lang#4183.  Needed for rust-lang#5656.
bors added a commit that referenced this issue Apr 10, 2013
…komatsakis

Cleanup substitutions and treatment of generics around traits in a number of ways

- In a TraitRef, use the self type consistently to refer to the Self type:
  - trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
  - trait ref in `A:Trait` has the self type `A`
  - trait ref associated with a trait decl has self type `Self`
  - trait ref associated with a supertype has self type `Self`
  - trait ref in an object type `@Trait` has no self type

- Rewrite `each_bound_traits_and_supertraits` to perform
  substitutions as it goes, and thus yield a series of trait refs
  that are always in the same 'namespace' as the type parameter
  bound given as input.  Before, we left this to the caller, but
  this doesn't work because the caller lacks adequare information
  to perform the type substitutions correctly.

- For provided methods, substitute the generics involved in the provided
  method correctly.

- Introduce TypeParameterDef, which tracks the bounds declared on a type
  parameter and brings them together with the def_id and (in the future)
  other information (maybe even the parameter's name!).

- Introduce Subst trait, which helps to cleanup a lot of the
  repetitive code involved with doing type substitution.

- Introduce Repr trait, which makes debug printouts far more convenient.

Fixes #4183.  Needed for #5656.

r? @catamorphism
@brendanzab
Copy link
Member Author

I think we can close this one now. Everything seems to be in order. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system
Projects
None yet
Development

No branches or pull requests

3 participants