@@ -37,10 +37,13 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
3737 a trait or new type instead") ;
3838 }
3939 }
40- }
4140
42- impl < ' cx , ' tcx , ' v > visit:: Visitor < ' v > for OrphanChecker < ' cx , ' tcx > {
43- fn visit_item ( & mut self , item : & ast:: Item ) {
41+ /// Checks exactly one impl for orphan rules and other such
42+ /// restrictions. In this fn, it can happen that multiple errors
43+ /// apply to a specific impl, so just return after reporting one
44+ /// to prevent inundating the user with a bunch of similar error
45+ /// reports.
46+ fn check_item ( & self , item : & ast:: Item ) {
4447 let def_id = ast_util:: local_def ( item. id ) ;
4548 match item. node {
4649 ast:: ItemImpl ( _, _, _, None , _, _) => {
@@ -63,13 +66,15 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
6366 span_err ! ( self . tcx. sess, item. span, E0118 ,
6467 "no base type found for inherent implementation; \
6568 implement a trait or new type instead") ;
69+ return ;
6670 }
6771 }
6872 }
6973 ast:: ItemImpl ( _, _, _, Some ( _) , _, _) => {
7074 // "Trait" impl
7175 debug ! ( "coherence2::orphan check: trait impl {}" , item. repr( self . tcx) ) ;
72- let trait_def_id = ty:: impl_trait_ref ( self . tcx , def_id) . unwrap ( ) . def_id ;
76+ let trait_ref = ty:: impl_trait_ref ( self . tcx , def_id) . unwrap ( ) ;
77+ let trait_def_id = trait_ref. def_id ;
7378 match traits:: orphan_check ( self . tcx , def_id) {
7479 Ok ( ( ) ) => { }
7580 Err ( traits:: OrphanCheckErr :: NoLocalInputType ) => {
@@ -80,6 +85,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
8085 types defined in this crate; \
8186 only traits defined in the current crate can be \
8287 implemented for arbitrary types") ;
88+ return ;
8389 }
8490 }
8591 Err ( traits:: OrphanCheckErr :: UncoveredTy ( param_ty) ) => {
@@ -89,9 +95,100 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
8995 some local type (e.g. `MyStruct<T>`); only traits defined in \
9096 the current crate can be implemented for a type parameter",
9197 param_ty. user_string( self . tcx) ) ;
98+ return ;
9299 }
93100 }
94101 }
102+
103+ // In addition to the above rules, we restrict impls of defaulted traits
104+ // so that they can only be implemented on structs/enums. To see why this
105+ // restriction exists, consider the following example (#22978). Imagine
106+ // that crate A defines a defaulted trait `Foo` and a fn that operates
107+ // on pairs of types:
108+ //
109+ // ```
110+ // // Crate A
111+ // trait Foo { }
112+ // impl Foo for .. { }
113+ // fn two_foos<A:Foo,B:Foo>(..) {
114+ // one_foo::<(A,B)>(..)
115+ // }
116+ // fn one_foo<T:Foo>(..) { .. }
117+ // ```
118+ //
119+ // This type-checks fine; in particular the fn
120+ // `two_foos` is able to conclude that `(A,B):Foo`
121+ // because `A:Foo` and `B:Foo`.
122+ //
123+ // Now imagine that crate B comes along and does the following:
124+ //
125+ // ```
126+ // struct A { }
127+ // struct B { }
128+ // impl Foo for A { }
129+ // impl Foo for B { }
130+ // impl !Send for (A, B) { }
131+ // ```
132+ //
133+ // This final impl is legal according to the orpan
134+ // rules, but it invalidates the reasoning from
135+ // `two_foos` above.
136+ debug ! ( "trait_ref={} trait_def_id={} trait_has_default_impl={}" ,
137+ trait_ref. repr( self . tcx) ,
138+ trait_def_id. repr( self . tcx) ,
139+ ty:: trait_has_default_impl( self . tcx, trait_def_id) ) ;
140+ if
141+ ty:: trait_has_default_impl ( self . tcx , trait_def_id) &&
142+ trait_def_id. krate != ast:: LOCAL_CRATE
143+ {
144+ let self_ty = trait_ref. self_ty ( ) ;
145+ let opt_self_def_id = match self_ty. sty {
146+ ty:: ty_struct( self_def_id, _) | ty:: ty_enum( self_def_id, _) =>
147+ Some ( self_def_id) ,
148+ ty:: ty_uniq( ..) =>
149+ self . tcx . lang_items . owned_box ( ) ,
150+ _ =>
151+ None
152+ } ;
153+
154+ let msg = match opt_self_def_id {
155+ // We only want to permit structs/enums, but not *all* structs/enums.
156+ // They must be local to the current crate, so that people
157+ // can't do `unsafe impl Send for Rc<SomethingLocal>` or
158+ // `impl !Send for Box<SomethingLocalAndSend>`.
159+ Some ( self_def_id) => {
160+ if self_def_id. krate == ast:: LOCAL_CRATE {
161+ None
162+ } else {
163+ Some ( format ! (
164+ "cross-crate traits with a default impl, like `{}`, \
165+ can only be implemented for a struct/enum type \
166+ defined in the current crate",
167+ ty:: item_path_str( self . tcx, trait_def_id) ) )
168+ }
169+ }
170+ _ => {
171+ Some ( format ! (
172+ "cross-crate traits with a default impl, like `{}`, \
173+ can only be implemented for a struct/enum type, \
174+ not `{}`",
175+ ty:: item_path_str( self . tcx, trait_def_id) ,
176+ self_ty. user_string( self . tcx) ) )
177+ }
178+ } ;
179+
180+ if let Some ( msg) = msg {
181+ span_err ! ( self . tcx. sess, item. span, E0321 , "{}" , msg) ;
182+ return ;
183+ }
184+ }
185+
186+ // Disallow *all* explicit impls of `Sized` for now.
187+ if Some ( trait_def_id) == self . tcx . lang_items . sized_trait ( ) {
188+ span_err ! ( self . tcx. sess, item. span, E0322 ,
189+ "explicit impls for the `Sized` trait are not permitted" ) ;
190+ return ;
191+ }
95192 }
96193 ast:: ItemDefaultImpl ( ..) => {
97194 // "Trait" impl
@@ -100,14 +197,20 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
100197 if trait_ref. def_id . krate != ast:: LOCAL_CRATE {
101198 span_err ! ( self . tcx. sess, item. span, E0318 ,
102199 "cannot create default implementations for traits outside the \
103- crate they're defined in; define a new trait instead.") ;
200+ crate they're defined in; define a new trait instead") ;
201+ return ;
104202 }
105203 }
106204 _ => {
107205 // Not an impl
108206 }
109207 }
208+ }
209+ }
110210
211+ impl < ' cx , ' tcx , ' v > visit:: Visitor < ' v > for OrphanChecker < ' cx , ' tcx > {
212+ fn visit_item ( & mut self , item : & ast:: Item ) {
213+ self . check_item ( item) ;
111214 visit:: walk_item ( self , item) ;
112215 }
113216}
0 commit comments