Skip to content

Delay all sized checks #100971

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
(_, ty)| {
let ty = self.resolve_vars_if_possible(ty);
same &=
!matches!(ty.kind(), ty::Error(_))
!ty.references_error()
&& last_ty.map_or(true, |last_ty| {
// FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
// *after* in the dependency graph.
Expand Down
12 changes: 2 additions & 10 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
);
self.require_type_is_sized(
self.normalize_associated_types_in(span, input),
span,
traits::SizedArgumentType(arg_span),
);
self.require_type_is_sized(input, span, traits::SizedArgumentType(arg_span));
}
}
// Here we want to prevent struct constructors from returning unsized types.
Expand All @@ -586,11 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.output(),
);
self.require_type_is_sized(
self.normalize_associated_types_in(expr.span, output),
expr.span,
traits::SizedReturnType,
);
self.require_type_is_sized(output, expr.span, traits::SizedReturnType);
}

// We always require that the type provided as the value for
Expand Down
21 changes: 19 additions & 2 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
Expand Down Expand Up @@ -437,7 +436,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
code: traits::ObligationCauseCode<'tcx>,
) {
if !ty.references_error() {
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
if let Some(deferred_sized_obligations) =
&mut *self.deferred_sized_obligations.borrow_mut()
{
deferred_sized_obligations.push((ty, span, code));
} else {
self.require_type_is_sized_eager(ty, span, code);
}
}
}

pub fn require_type_is_sized_eager(
&self,
ty: Ty<'tcx>,
span: Span,
code: traits::ObligationCauseCode<'tcx>,
) {
let ty = self.normalize_associated_types_in(span, ty);
if !ty.references_error() {
let lang_item = self.tcx.require_lang_item(hir::LangItem::Sized, None);
self.require_type_meets(ty, span, code, lang_item);
}
}
Expand Down
15 changes: 5 additions & 10 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::check::{
use crate::structured_errors::StructuredDiagnostic;

use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
Expand Down Expand Up @@ -1618,12 +1617,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
) {
// Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
// other errors that have the same span and predicate can also get fixed,
// even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
// This is important since if we adjust one span but not the other, then
// we will have "duplicated" the error on the UI side.
let mut remap_cause = FxHashSet::default();
let mut not_adjusted = vec![];

for error in errors {
Expand All @@ -1634,6 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Store both the predicate and the predicate *without constness*
// since sometimes we instantiate and check both of these in a
// method call, for example.
let mut remap_cause = self.remap_fulfillment_cause.borrow_mut();
remap_cause.insert((
before_span,
error.obligation.predicate,
Expand All @@ -1652,9 +1646,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

for error in not_adjusted {
for (span, predicate, cause) in &remap_cause {
for (span, predicate, cause) in &*self.remap_fulfillment_cause.borrow() {
if *predicate == error.obligation.predicate
&& span.contains(error.obligation.cause.span)
&& span.overlaps(error.obligation.cause.span)
{
error.obligation.cause = cause.clone();
continue;
Expand All @@ -1667,7 +1661,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
error: &mut traits::FulfillmentError<'tcx>,
) -> bool {
let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
let (traits::ExprItemObligation(def_id, hir_id, idx)
| traits::ExprBindingObligation(def_id, _, hir_id, idx))
= *error.obligation.cause.code().peel_derives() else { return false; };
let hir = self.tcx.hir();
let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod checks;
mod suggestions;

pub use _impl::*;
use rustc_data_structures::fx::FxHashSet;
pub use suggestions::*;

use crate::astconv::AstConv;
Expand Down Expand Up @@ -129,6 +130,14 @@ pub struct FnCtxt<'a, 'tcx> {

/// True if the return type has an Opaque type
pub(super) return_type_has_opaque: bool,

// Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
// other errors that have the same span and predicate can also get fixed,
// even if their `ObligationCauseCode` isn't an `Expr{Item,Binding}Obligation`.
// This is important since if we adjust one span but not the other, then
// we will have "duplicated" the error on the UI side.
pub(super) remap_fulfillment_cause:
RefCell<FxHashSet<(Span, ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
}

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Expand Down Expand Up @@ -156,6 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
inh,
return_type_pre_known: true,
return_type_has_opaque: false,
remap_fulfillment_cause: Default::default(),
}
}

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_typeck/src/check/inherited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub struct Inherited<'a, 'tcx> {

pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,

// Some additional `Sized` obligations badly affect type inference.
// These obligations are added in a later stage of typeck.
pub(super) deferred_sized_obligations:
RefCell<Option<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>>,

// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
Expand Down Expand Up @@ -112,6 +117,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
infcx,
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
locals: RefCell::new(Default::default()),
deferred_sized_obligations: RefCell::new(Some(Vec::new())),
deferred_call_resolutions: RefCell::new(Default::default()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_transmute_checks: RefCell::new(Vec::new()),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,10 @@ fn typeck_with_fallback<'tcx>(
fcx
};

for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().take().unwrap() {
fcx.require_type_is_sized_eager(ty, span, code);
}

let fallback_has_occurred = fcx.type_inference_fallback();

// Even though coercion casts provide type hints, we check casts after fallback for
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/asm/type-check-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ fn main() {
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
//~| ERROR cannot use value of type `[u64]` for inline assembly
asm!("{}", out(reg) v[..]);
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
//~| ERROR cannot use value of type `[u64]` for inline assembly
//~^ ERROR cannot use value of type `[u64]` for inline assembly
asm!("{}", inout(reg) v[..]);
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
//~| ERROR cannot use value of type `[u64]` for inline assembly
//~^ ERROR cannot use value of type `[u64]` for inline assembly

// Constants must be... constant

Expand Down
40 changes: 11 additions & 29 deletions src/test/ui/asm/type-check-1.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:42:26
--> $DIR/type-check-1.rs:40:26
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
Expand All @@ -8,7 +8,7 @@ LL | asm!("{}", const x);
| ^ non-constant value

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:45:36
--> $DIR/type-check-1.rs:43:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
Expand All @@ -17,7 +17,7 @@ LL | asm!("{}", const const_foo(x));
| ^ non-constant value

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:48:36
--> $DIR/type-check-1.rs:46:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
Expand All @@ -26,7 +26,7 @@ LL | asm!("{}", const const_bar(x));
| ^ non-constant value

error: invalid `sym` operand
--> $DIR/type-check-1.rs:50:24
--> $DIR/type-check-1.rs:48:24
|
LL | asm!("{}", sym x);
| ^ is a local variable
Expand Down Expand Up @@ -54,24 +54,6 @@ LL | asm!("{}", in(reg) v[..]);
= help: the trait `Sized` is not implemented for `[u64]`
= note: all inline asm arguments must have a statically known size

error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
--> $DIR/type-check-1.rs:26:29
|
LL | asm!("{}", out(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u64]`
= note: all inline asm arguments must have a statically known size

error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
--> $DIR/type-check-1.rs:29:31
|
LL | asm!("{}", inout(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u64]`
= note: all inline asm arguments must have a statically known size

error: cannot use value of type `[u64]` for inline assembly
--> $DIR/type-check-1.rs:23:28
|
Expand All @@ -89,21 +71,21 @@ LL | asm!("{}", out(reg) v[..]);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly

error: cannot use value of type `[u64]` for inline assembly
--> $DIR/type-check-1.rs:29:31
--> $DIR/type-check-1.rs:28:31
|
LL | asm!("{}", inout(reg) v[..]);
| ^^^^^
|
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly

error[E0308]: mismatched types
--> $DIR/type-check-1.rs:58:26
--> $DIR/type-check-1.rs:56:26
|
LL | asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`

error[E0308]: mismatched types
--> $DIR/type-check-1.rs:60:26
--> $DIR/type-check-1.rs:58:26
|
LL | asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
Expand All @@ -112,7 +94,7 @@ LL | asm!("{}", const 0 as *mut u8);
found raw pointer `*mut u8`

error[E0308]: mismatched types
--> $DIR/type-check-1.rs:62:26
--> $DIR/type-check-1.rs:60:26
|
LL | asm!("{}", const &0);
| ^^ expected integer, found `&{integer}`
Expand All @@ -124,21 +106,21 @@ LL + asm!("{}", const 0);
|

error[E0308]: mismatched types
--> $DIR/type-check-1.rs:76:25
--> $DIR/type-check-1.rs:74:25
|
LL | global_asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`

error[E0308]: mismatched types
--> $DIR/type-check-1.rs:78:25
--> $DIR/type-check-1.rs:76:25
|
LL | global_asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
|
= note: expected type `{integer}`
found raw pointer `*mut u8`

error: aborting due to 17 previous errors
error: aborting due to 15 previous errors

Some errors have detailed explanations: E0277, E0308, E0435.
For more information about an error, try `rustc --explain E0277`.
2 changes: 0 additions & 2 deletions src/test/ui/box/into-boxed-slice-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ fn main() {
let boxed_slice = Box::new([1,2,3]) as Box<[u8]>;
let _ = Box::into_boxed_slice(boxed_slice);
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
//~^^ ERROR the size for values of type `[u8]` cannot be known at compilation time
let boxed_trait: Box<dyn Debug> = Box::new(5u8);
let _ = Box::into_boxed_slice(boxed_trait);
//~^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time
//~^^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time
}
22 changes: 2 additions & 20 deletions src/test/ui/box/into-boxed-slice-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,8 @@ note: required by a bound in `Box::<T, A>::into_boxed_slice`
LL | impl<T, A: Allocator> Box<T, A> {
| ^ required by this bound in `Box::<T, A>::into_boxed_slice`

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/into-boxed-slice-fail.rs:7:13
|
LL | let _ = Box::into_boxed_slice(boxed_slice);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: slice and array elements must have `Sized` type

error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/into-boxed-slice-fail.rs:11:35
--> $DIR/into-boxed-slice-fail.rs:10:35
|
LL | let _ = Box::into_boxed_slice(boxed_trait);
| --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -37,15 +28,6 @@ note: required by a bound in `Box::<T, A>::into_boxed_slice`
LL | impl<T, A: Allocator> Box<T, A> {
| ^ required by this bound in `Box::<T, A>::into_boxed_slice`

error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/into-boxed-slice-fail.rs:11:13
|
LL | let _ = Box::into_boxed_slice(boxed_trait);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Debug`
= note: slice and array elements must have `Sized` type

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

For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0282.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
fn main() {
let x = "hello".chars().rev().collect(); //~ ERROR E0282
let x: _ = "hello".chars().rev().collect(); //~ ERROR E0282
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This turned into E0283 for some reason, unless I add this : _ annotation...?

}
12 changes: 6 additions & 6 deletions src/test/ui/error-codes/E0282.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0282]: type annotations needed
--> $DIR/E0282.rs:2:9
--> $DIR/E0282.rs:2:38
|
LL | let x = "hello".chars().rev().collect();
| ^
LL | let x: _ = "hello".chars().rev().collect();
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect`
|
help: consider giving `x` an explicit type
help: consider specifying the generic argument
|
LL | let x: _ = "hello".chars().rev().collect();
| +++
LL | let x: _ = "hello".chars().rev().collect::<B>();
| +++++

error: aborting due to previous error

Expand Down
Loading