Skip to content

Commit

Permalink
Fail candidate assembly for erroneous types
Browse files Browse the repository at this point in the history
Trait predicates for types which have errors may still
evaluate to OK leading to downstream ICEs. Now we return
a selection error for such types in candidate assembly and
thereby prevent such issues
  • Loading branch information
gurry committed Apr 15, 2024
1 parent 59c38c0 commit 4ee780a
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// Already reported in the query.
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) |
// Already reported.
Overflow(OverflowError::Error(guar)) => return guar,
Overflow(OverflowError::Error(guar)) => {
self.set_tainted_by_errors(guar);
return guar
},

Overflow(_) => {
bug!("overflow should be handled before the `report_selection_error` path");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else if lang_items.sized_trait() == Some(def_id) {
// Sized is never implementable by end-users, it is
// always automatically computed.

// FIXME: Consider moving this check to the top level as it
// may also be useful for predicates other than `Sized`
// Error type cannot possibly implement `Sized` (fixes #123154)
if let Err(e) = obligation.predicate.skip_binder().self_ty().error_reported() {
return Err(SelectionError::Overflow(e.into()));
}

let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
} else if lang_items.unsize_trait() == Some(def_id) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ fn adt_sized_constraint<'tcx>(
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();

let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
if constraint_ty.references_error() {
return None;
if let Err(guar) = constraint_ty.error_reported() {
return Some(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
}

// perf hack: if there is a `constraint_ty: Sized` bound, then we know
Expand Down
1 change: 0 additions & 1 deletion tests/ui/closures/issue-78720.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
fn server() -> impl {
//~^ ERROR at least one trait must be specified
//~| ERROR type annotations needed
().map2(|| "")
}

Expand Down
16 changes: 5 additions & 11 deletions tests/ui/closures/issue-78720.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | fn server() -> impl {
| ^^^^

error[E0412]: cannot find type `F` in this scope
--> $DIR/issue-78720.rs:14:12
--> $DIR/issue-78720.rs:13:12
|
LL | _func: F,
| ^
Expand All @@ -22,14 +22,8 @@ help: you might be missing a type parameter
LL | struct Map2<Segment2, F> {
| +++

error[E0282]: type annotations needed
--> $DIR/issue-78720.rs:1:16
|
LL | fn server() -> impl {
| ^^^^ cannot infer type

error[E0308]: mismatched types
--> $DIR/issue-78720.rs:8:39
--> $DIR/issue-78720.rs:7:39
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^ expected `Map2<F>`, found `()`
Expand All @@ -38,7 +32,7 @@ LL | fn map2<F>(self, f: F) -> Map2<F> {}
found unit type `()`

error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/issue-78720.rs:8:16
--> $DIR/issue-78720.rs:7:16
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^^^ doesn't have a size known at compile-time
Expand All @@ -53,7 +47,7 @@ help: function arguments must have a statically known size, borrowed types alway
LL | fn map2<F>(&self, f: F) -> Map2<F> {}
| +

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0277, E0282, E0308, E0412.
Some errors have detailed explanations: E0277, E0308, E0412.
For more information about an error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ impl Opcode2 {
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
move |i| match msg_type {
Opcode2::OP2 => unimplemented!(),
//~^ ERROR could not evaluate constant pattern
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ help: you might be missing a type parameter
LL | pub struct Opcode2<S>(&'a S);
| +++

error: could not evaluate constant pattern
--> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
|
LL | Opcode2::OP2 => unimplemented!(),
| ^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0261, E0412.
For more information about an error, try `rustc --explain E0261`.
15 changes: 15 additions & 0 deletions tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Regression test for #123154

struct AA {
pub data: [&usize]
//~^ ERROR missing lifetime specifier
}

impl AA {
const fn new() -> Self { }
//~^ ERROR mismatched types
}

static ST: AA = AA::new();

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0106]: missing lifetime specifier
--> $DIR/ice-unsized-struct-const-eval-123154.rs:4:16
|
LL | pub data: [&usize]
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL ~ struct AA<'a> {
LL ~ pub data: [&'a usize]
|

error[E0308]: mismatched types
--> $DIR/ice-unsized-struct-const-eval-123154.rs:9:23
|
LL | const fn new() -> Self { }
| --- ^^^^ expected `AA`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0106, E0308.
For more information about an error, try `rustc --explain E0106`.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl<T, D> MyTrait<T> for D {
}

impl<T> MyTrait<T> for BadStruct {
//~^ ERROR: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
fn foo() {}
}

Expand Down
14 changes: 12 additions & 2 deletions tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ error[E0412]: cannot find type `MissingType` in this scope
LL | err: MissingType
| ^^^^^^^^^^^ not found in this scope

error: aborting due to 1 previous error
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
--> $DIR/issue-68830-spurious-diagnostics.rs:19:1
|
LL | impl<T, D> MyTrait<T> for D {
| --------------------------- first implementation here
...
LL | impl<T> MyTrait<T> for BadStruct {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `BadStruct`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0412`.
Some errors have detailed explanations: E0119, E0412.
For more information about an error, try `rustc --explain E0119`.

0 comments on commit 4ee780a

Please sign in to comment.