@@ -158,7 +158,7 @@ impl AssociatedTyValue {
158
158
/// type IntoIter<'a>: 'a;
159
159
/// }
160
160
/// ```
161
- ///
161
+ ///
162
162
/// Then for the following impl:
163
163
/// ```notrust
164
164
/// impl<T> Iterable for Vec<T> {
@@ -300,7 +300,12 @@ impl StructDatum {
300
300
// forall<T> { WF(Foo<T>) :- (T: Eq). }
301
301
// forall<T> { FromEnv(T: Eq) :- FromEnv(Foo<T>). }
302
302
//
303
- // If the type Foo is not marked `extern`, we also generate:
303
+ // If the type Foo is marked `extern`, we also generate:
304
+ //
305
+ // forall<T> { IsExternal(Foo<T>) }
306
+ // forall<T> { IsDeeplyExternal(Foo<T>) :- IsDeeplyExternal(T) }
307
+ //
308
+ // Otherwise, if the type Foo is not marked `extern`, we generate:
304
309
//
305
310
// forall<T> { IsLocal(Foo<T>) }
306
311
//
@@ -312,6 +317,8 @@ impl StructDatum {
312
317
// We generate the following clause:
313
318
//
314
319
// forall<T> { IsLocal(Box<T>) :- IsLocal(T) }
320
+ // forall<T> { IsExternal(Box<T>) :- IsExternal(T) }
321
+ // forall<T> { IsDeeplyExternal(Box<T>) :- IsDeeplyExternal(T) }
315
322
316
323
let wf = self . binders . map_ref ( |bound_datum| {
317
324
ProgramClauseImplication {
@@ -350,18 +357,45 @@ impl StructDatum {
350
357
assert_eq ! ( self . binders. value. self_ty. len_type_parameters( ) , 1 ,
351
358
"Only fundamental types with a single parameter are supported" ) ;
352
359
353
- let local_fundamental = self . binders . map_ref ( |bound_datum| ProgramClauseImplication {
354
- consequence : DomainGoal :: IsLocal ( bound_datum. self_ty . clone ( ) . cast ( ) ) ,
355
- conditions : vec ! [
356
- DomainGoal :: IsLocal (
357
- // This unwrap is safe because we asserted above for the presence of a type
358
- // parameter
359
- bound_datum. self_ty. first_type_parameter( ) . unwrap( )
360
- ) . cast( ) ,
361
- ] ,
360
+ // Fundamental types often have rules in the form of:
361
+ // Goal(FundamentalType<T>) :- Goal(T)
362
+ // This macro makes creating that kind of clause easy
363
+ macro_rules! fundamental_rule {
364
+ ( $goal: ident) => {
365
+ clauses. push( self . binders. map_ref( |bound_datum| ProgramClauseImplication {
366
+ consequence: DomainGoal :: $goal( bound_datum. self_ty. clone( ) . cast( ) ) ,
367
+ conditions: vec![
368
+ DomainGoal :: $goal(
369
+ // This unwrap is safe because we asserted above for the presence of a type
370
+ // parameter
371
+ bound_datum. self_ty. first_type_parameter( ) . unwrap( )
372
+ ) . cast( ) ,
373
+ ] ,
374
+ } ) . cast( ) ) ;
375
+ } ;
376
+ }
377
+
378
+ fundamental_rule ! ( IsLocal ) ;
379
+ fundamental_rule ! ( IsExternal ) ;
380
+ fundamental_rule ! ( IsDeeplyExternal ) ;
381
+ } else {
382
+ // The type is just extern and not fundamental
383
+
384
+ let is_external = self . binders . map_ref ( |bound_datum| ProgramClauseImplication {
385
+ consequence : DomainGoal :: IsExternal ( bound_datum. self_ty . clone ( ) . cast ( ) ) ,
386
+ conditions : Vec :: new ( ) ,
362
387
} ) . cast ( ) ;
363
388
364
- clauses. push ( local_fundamental) ;
389
+ clauses. push ( is_external) ;
390
+
391
+ let is_deeply_external = self . binders . map_ref ( |bound_datum| ProgramClauseImplication {
392
+ consequence : DomainGoal :: IsDeeplyExternal ( bound_datum. self_ty . clone ( ) . cast ( ) ) ,
393
+ conditions : bound_datum. self_ty . type_parameters ( )
394
+ . map ( |ty| DomainGoal :: IsDeeplyExternal ( ty) . cast ( ) )
395
+ . collect ( ) ,
396
+ } ) . cast ( ) ;
397
+
398
+ clauses. push ( is_deeply_external) ;
365
399
}
366
400
367
401
let condition = DomainGoal :: FromEnv (
@@ -413,6 +447,43 @@ impl TraitDatum {
413
447
//
414
448
// forall<Self, T> { (Self: Ord<T>) :- FromEnv(Self: Ord<T>) }
415
449
// forall<Self, T> { FromEnv(Self: Eq<T>) :- FromEnv(Self: Ord<T>) }
450
+ //
451
+ // As specified in the orphan rules, if a trait is not marked `extern`, the current crate
452
+ // can implement it for any type. To represent that, we generate:
453
+ //
454
+ // // `Ord<T>` would not be `extern` when compiling `std`
455
+ // forall<Self, T> { LocalImplAllowed(Self: Ord<T>) }
456
+ //
457
+ // For traits that are `extern` (i.e. not in the current crate), the orphan rules dictate
458
+ // that impls are allowed as long as at least one type parameter is local and each type
459
+ // prior to that is *deeply* external. That means that each type prior to the first local
460
+ // type cannot contain any of the type parameters of the impl.
461
+ //
462
+ // This rule is fairly complex, so we expand it and generate a program clause for each
463
+ // possible case. This is represented as follows:
464
+ //
465
+ // // for `extern trait Foo<T, U, V> where Self: Eq<T> { ... }`
466
+ // forall<Self, T, U, V> {
467
+ // LocalImplAllowed(Self: Foo<T, U, V>) :- IsLocal(Self)
468
+ // }
469
+ // forall<Self, T, U, V> {
470
+ // LocalImplAllowed(Self: Foo<T, U, V>) :-
471
+ // IsDeeplyExternal(Self),
472
+ // IsLocal(T)
473
+ // }
474
+ // forall<Self, T, U, V> {
475
+ // LocalImplAllowed(Self: Foo<T, U, V>) :-
476
+ // IsDeeplyExternal(Self),
477
+ // IsDeeplyExternal(T),
478
+ // IsLocal(U)
479
+ // }
480
+ // forall<Self, T, U, V> {
481
+ // LocalImplAllowed(Self: Foo<T, U, V>) :-
482
+ // IsDeeplyExternal(Self),
483
+ // IsDeeplyExternal(T),
484
+ // IsDeeplyExternal(U),
485
+ // IsLocal(V)
486
+ // }
416
487
417
488
let trait_ref = self . binders . value . trait_ref . clone ( ) ;
418
489
@@ -437,6 +508,38 @@ impl TraitDatum {
437
508
} ) . cast ( ) ;
438
509
439
510
let mut clauses = vec ! [ wf] ;
511
+
512
+ if !self . binders . value . flags . external {
513
+ let impl_allowed = self . binders . map_ref ( |bound_datum|
514
+ ProgramClauseImplication {
515
+ consequence : DomainGoal :: LocalImplAllowed ( bound_datum. trait_ref . clone ( ) ) ,
516
+ conditions : Vec :: new ( ) ,
517
+ }
518
+ ) . cast ( ) ;
519
+
520
+ clauses. push ( impl_allowed) ;
521
+ } else {
522
+ // The number of parameters will always be at least 1 because of the Self parameter
523
+ // that is automatically added to every trait. This is important because otherwise
524
+ // the added program clauses would not have any conditions.
525
+
526
+ let type_parameters: Vec < _ > = self . binders . value . trait_ref . type_parameters ( ) . collect ( ) ;
527
+
528
+ for i in 0 ..type_parameters. len ( ) {
529
+ let impl_maybe_allowed = self . binders . map_ref ( |bound_datum|
530
+ ProgramClauseImplication {
531
+ consequence : DomainGoal :: LocalImplAllowed ( bound_datum. trait_ref . clone ( ) ) ,
532
+ conditions : ( 0 ..i)
533
+ . map ( |j| DomainGoal :: IsDeeplyExternal ( type_parameters[ j] . clone ( ) ) . cast ( ) )
534
+ . chain ( iter:: once ( DomainGoal :: IsLocal ( type_parameters[ i] . clone ( ) ) . cast ( ) ) )
535
+ . collect ( ) ,
536
+ }
537
+ ) . cast ( ) ;
538
+
539
+ clauses. push ( impl_maybe_allowed) ;
540
+ }
541
+ }
542
+
440
543
let condition = DomainGoal :: FromEnv ( FromEnv :: Trait ( trait_ref. clone ( ) ) ) ;
441
544
442
545
for wc in self . binders
0 commit comments