]> git.lizzy.rs Git - rust.git/commitdiff
Reenable trivial bounds
authorMatthew Jasper <mjjasper1@gmail.com>
Fri, 8 Jun 2018 16:00:03 +0000 (17:00 +0100)
committerMatthew Jasper <mjjasper1@gmail.com>
Fri, 8 Jun 2018 16:00:03 +0000 (17:00 +0100)
Removes extra global bounds at the winnowing stage rather than when
normalizing the param_env. This avoids breaking inference when there is
a global bound.

13 files changed:
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/test/ui/feature-gate-trivial_bounds.rs
src/test/ui/feature-gate-trivial_bounds.stderr
src/test/ui/trivial-bounds-inconsistent-associated-functions.rs
src/test/ui/trivial-bounds-inconsistent-copy-reborrow.rs
src/test/ui/trivial-bounds-inconsistent-copy.rs
src/test/ui/trivial-bounds-inconsistent-sized.rs
src/test/ui/trivial-bounds-inconsistent-well-formed.rs
src/test/ui/trivial-bounds-inconsistent.rs
src/test/ui/trivial-bounds-leak-copy.rs
src/test/ui/trivial-bounds-leak.rs
src/test/ui/trivial-bounds-lint.rs

index 3bd4e11b0e8b9708abd8324bc970cc3d69c86045..e284b3fc75a6418475c3f7934f63dc8dae14fdbf 100644 (file)
@@ -648,13 +648,8 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let predicates: Vec<_> =
         util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
-        .filter(|p| !p.is_global() || p.has_late_bound_regions()) // (*)
         .collect();
 
-    // (*) FIXME(#50825) This shouldn't be needed.
-    // Removing the bounds here stopped them from being prefered in selection.
-    // See the issue-50825 ui tests for examples
-
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
            predicates);
 
index 7a52a5cbf5acc69713a9dd58c5186e8c0eb63c1b..08af80543dff2c51a936c2584fc023708f5f6be5 100644 (file)
@@ -2011,9 +2011,6 @@ fn assemble_candidates_for_unsizing(&mut self,
     // attempt to evaluate recursive bounds to see if they are
     // satisfied.
 
-    /// Returns true if `candidate_i` should be dropped in favor of
-    /// `candidate_j`.  Generally speaking we will drop duplicate
-    /// candidates and prefer where-clause candidates.
     /// Returns true if `victim` should be dropped in favor of
     /// `other`.  Generally speaking we will drop duplicate
     /// candidates and prefer where-clause candidates.
@@ -2025,13 +2022,46 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
         other: &EvaluatedCandidate<'tcx>)
         -> bool
     {
+        // Check if a bound would previously have been removed when normalizing
+        // the param_env so that it can be given the lowest priority. See
+        // #50825 for the motivation for this.
+        let is_global = |cand: &ty::PolyTraitRef<'_>| {
+            cand.is_global() && !cand.has_late_bound_regions()
+        };
+
         if victim.candidate == other.candidate {
             return true;
         }
 
         match other.candidate {
+            ParamCandidate(ref cand) => match victim.candidate {
+                AutoImplCandidate(..) => {
+                    bug!(
+                        "default implementations shouldn't be recorded \
+                         when there are other valid candidates");
+                }
+                ImplCandidate(..) |
+                ClosureCandidate |
+                GeneratorCandidate |
+                FnPointerCandidate |
+                BuiltinObjectCandidate |
+                BuiltinUnsizeCandidate |
+                BuiltinCandidate { .. } => {
+                    // Global bounds from the where clause should be ignored
+                    // here (see issue #50825). Otherwise, we have a where
+                    // clause so don't go around looking for impls.
+                    !is_global(cand)
+                }
+                ObjectCandidate |
+                ProjectionCandidate => {
+                    // Arbitrarily give param candidates priority
+                    // over projection and object candidates.
+                    !is_global(cand)
+                },
+                ParamCandidate(..) => false,
+            },
             ObjectCandidate |
-            ParamCandidate(_) | ProjectionCandidate => match victim.candidate {
+            ProjectionCandidate => match victim.candidate {
                 AutoImplCandidate(..) => {
                     bug!(
                         "default implementations shouldn't be recorded \
@@ -2044,8 +2074,6 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                 BuiltinObjectCandidate |
                 BuiltinUnsizeCandidate |
                 BuiltinCandidate { .. } => {
-                    // We have a where-clause so don't go around looking
-                    // for impls.
                     true
                 }
                 ObjectCandidate |
@@ -2054,22 +2082,44 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                     // over projection and object candidates.
                     true
                 },
-                ParamCandidate(..) => false,
+                ParamCandidate(ref cand) => is_global(cand),
             },
             ImplCandidate(other_def) => {
                 // See if we can toss out `victim` based on specialization.
                 // This requires us to know *for sure* that the `other` impl applies
                 // i.e. EvaluatedToOk:
                 if other.evaluation == EvaluatedToOk {
-                    if let ImplCandidate(victim_def) = victim.candidate {
-                        let tcx = self.tcx().global_tcx();
-                        return tcx.specializes((other_def, victim_def)) ||
-                            tcx.impls_are_allowed_to_overlap(other_def, victim_def);
+                    match victim.candidate {
+                        ImplCandidate(victim_def) => {
+                            let tcx = self.tcx().global_tcx();
+                            return tcx.specializes((other_def, victim_def)) ||
+                                tcx.impls_are_allowed_to_overlap(other_def, victim_def);
+                        }
+                        ParamCandidate(ref cand) => {
+                            // Prefer the impl to a global where clause candidate.
+                            return is_global(cand);
+                        }
+                        _ => ()
                     }
                 }
 
                 false
             },
+            ClosureCandidate |
+            GeneratorCandidate |
+            FnPointerCandidate |
+            BuiltinObjectCandidate |
+            BuiltinUnsizeCandidate |
+            BuiltinCandidate { .. } => {
+                match victim.candidate {
+                    ParamCandidate(ref cand) => {
+                        // Prefer these to a global where-clause bound
+                        // (see issue #50825)
+                        is_global(cand) && other.evaluation == EvaluatedToOk
+                    }
+                    _ => false,
+                }
+            }
             _ => false
         }
     }
index e72b8782e50d59fcb3e441a8e71f43d66be723a1..dba66e0b69bfc916d0be64ef466dffe694831172 100644 (file)
@@ -28,7 +28,7 @@ union U where i32: Foo { f: i32 } //~ ERROR
 type Y where i32: Foo = (); // OK - bound is ignored
 
 impl Foo for () where i32: Foo { //~ ERROR
-    fn test(&self) { //~ ERROR
+    fn test(&self) {
         3i32.test();
         Foo::test(&4i32);
         generic_function(5i32);
@@ -60,7 +60,7 @@ struct Dst<X: ?Sized> {
 }
 
 struct TwoStrs(str, str) where str: Sized; //~ ERROR
-//~^ ERROR
+
 
 fn unsized_local() where Dst<A>: Sized { //~ ERROR
     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
index 32b263119e5e266e0d2ee1607e71476bb9bc6045..9c2c80600b8c8f0f80204850a963298e5a62e7fd 100644 (file)
@@ -38,7 +38,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/feature-gate-trivial_bounds.rs:30:1
    |
 LL | / impl Foo for () where i32: Foo { //~ ERROR
-LL | |     fn test(&self) { //~ ERROR
+LL | |     fn test(&self) {
 LL | |         3i32.test();
 LL | |         Foo::test(&4i32);
 LL | |         generic_function(5i32);
@@ -97,15 +97,6 @@ LL | struct TwoStrs(str, str) where str: Sized; //~ ERROR
    = help: see issue #48214
    = help: add #![feature(trivial_bounds)] to the crate attributes to enable
 
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:62:16
-   |
-LL | struct TwoStrs(str, str) where str: Sized; //~ ERROR
-   |                ^^^ `str` does not have a constant size known at compile-time
-   |
-   = help: the trait `std::marker::Sized` is not implemented for `str`
-   = note: only the last field of a struct may have a dynamically sized type
-
 error[E0277]: the trait bound `A + 'static: std::marker::Sized` is not satisfied in `Dst<A + 'static>`
   --> $DIR/feature-gate-trivial_bounds.rs:65:1
    |
@@ -131,22 +122,6 @@ LL | | }
    = help: see issue #48214
    = help: add #![feature(trivial_bounds)] to the crate attributes to enable
 
-error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/feature-gate-trivial_bounds.rs:31:5
-   |
-LL | /     fn test(&self) { //~ ERROR
-LL | |         3i32.test();
-LL | |         Foo::test(&4i32);
-LL | |         generic_function(5i32);
-LL | |     }
-   | |_____^ the trait `Foo` is not implemented for `i32`
-   |
-note: required by `Foo`
-  --> $DIR/feature-gate-trivial_bounds.rs:14:1
-   |
-LL | pub trait Foo {
-   | ^^^^^^^^^^^^^
-
-error: aborting due to 13 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 4cacbc2c91445d76d06ffb2df6e69035d0c70830..49c9df95bc7720d347463c32d4e921351cdc5bd2 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // run-pass
 // Inconsistent bounds with trait implementations
 
index a743b4296980d44fc6c21d307923f9c741659f7c..2c4d9d813856c857d416fb660ffa5efdc0b97777 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // Check that reborrows are still illegal with Copy mutable references
 #![feature(trivial_bounds)]
 #![allow(unused)]
index f73c96a002d43cd7f1292cf72b1e10c013ecd96d..375885a02c75a56f70217508cae3ece7b8558754 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // run-pass
 // Check tautalogically false `Copy` bounds
 #![feature(trivial_bounds)]
index 11f0080fbabf127c9aaf9b34bcad29de3c89a1b5..14ba11c44de138639e830677d847907c29556f50 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // run-pass
 // Check tautalogically false `Sized` bounds
 #![feature(trivial_bounds)]
index a78ecdc8ff3d488cc8270a64bcc31b0624f9f43d..5fcdbfc437a81387c402e1d05f9f6337af34d916 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // run-pass
 // Test that inconsistent bounds are used in well-formedness checks
 #![feature(trivial_bounds)]
index c8e8c320bc5ff4dcf3149c094eb953adf6ffea5c..2c8b873b8c9462db590283b28bf0778bd62ac0e4 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // run-pass
 
 // Check that tautalogically false bounds are accepted, and are used
index 6f000006ca9b063168c97d8b5a41f1fbe1916ea6..9850ec2bd1fc0b8e946cac2c9375cdd92d96cecd 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // Check that false Copy bounds don't leak
 #![feature(trivial_bounds)]
 
index 15dee64f70e75ad7d6c232c49e740137f72dbad3..98cb5b2b503325f9e37cfaccae68bca781cca798 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 // Check that false bounds don't leak
 #![feature(trivial_bounds)]
 
index e37600a653a90a5c8c9ec9c5a4f781ec0fbd1924..e6988cb9f8bfe5689007c40e7d80469be4967983 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test FIXME(#50825)
 #![feature(trivial_bounds)]
 #![allow(unused)]
 #![deny(trivial_bounds)]