mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #95526 - Dylan-DPC:rollup-0ikl5l5, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #91416 (Specialize infinite-type "insert some indirection" suggestion for Option) - #95384 (Update target_has_atomic documentation for stabilization) - #95517 (small rustc_borrowck cleanup) - #95520 (Fix typos in core::ptr docs) - #95523 (remove unused field from `infcx`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0677edc86e
@ -253,8 +253,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
let constraint_sets: Vec<_> = unnormalized_input_output_tys
|
||||
.flat_map(|ty| {
|
||||
debug!("build: input_or_output={:?}", ty);
|
||||
// We add implied bounds from both the unnormalized and normalized ty
|
||||
// See issue #87748
|
||||
// We only add implied bounds for the normalized type as the unnormalized
|
||||
// type may not actually get checked by the caller.
|
||||
//
|
||||
// Can otherwise be unsound, see #91068.
|
||||
let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
|
||||
.param_env
|
||||
.and(type_op::normalize::Normalize::new(ty))
|
||||
|
@ -1899,7 +1899,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
ObligationCause::new(
|
||||
span,
|
||||
self.tcx().hir().local_def_id_to_hir_id(def_id),
|
||||
traits::ObligationCauseCode::RepeatVec(is_const_fn),
|
||||
traits::ObligationCauseCode::RepeatElementCopy {
|
||||
is_const_fn,
|
||||
},
|
||||
),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::TraitRef::new(
|
||||
|
@ -65,7 +65,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
Self {
|
||||
tcx: self.tcx.clone(),
|
||||
defining_use_anchor: self.defining_use_anchor.clone(),
|
||||
reveal_defining_opaque_types: self.reveal_defining_opaque_types.clone(),
|
||||
in_progress_typeck_results: self.in_progress_typeck_results.clone(),
|
||||
inner: self.inner.clone(),
|
||||
skip_leak_check: self.skip_leak_check.clone(),
|
||||
|
@ -290,10 +290,6 @@ pub struct InferCtxt<'a, 'tcx> {
|
||||
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
|
||||
pub defining_use_anchor: Option<LocalDefId>,
|
||||
|
||||
/// Used by WF-checking to not have to figure out hidden types itself, but
|
||||
/// to just invoke type_of to get the already computed hidden type from typeck.
|
||||
pub reveal_defining_opaque_types: bool,
|
||||
|
||||
/// During type-checking/inference of a body, `in_progress_typeck_results`
|
||||
/// contains a reference to the typeck results being built up, which are
|
||||
/// used for reading closure kinds/signatures as they are inferred,
|
||||
@ -569,7 +565,6 @@ pub struct InferCtxtBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
||||
defining_use_anchor: Option<LocalDefId>,
|
||||
reveal_defining_opaque_types: bool,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
@ -578,12 +573,7 @@ pub trait TyCtxtInferExt<'tcx> {
|
||||
|
||||
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
InferCtxtBuilder {
|
||||
tcx: self,
|
||||
defining_use_anchor: None,
|
||||
fresh_typeck_results: None,
|
||||
reveal_defining_opaque_types: false,
|
||||
}
|
||||
InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
|
||||
}
|
||||
}
|
||||
|
||||
@ -607,13 +597,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
self
|
||||
}
|
||||
|
||||
/// WF-checking doesn't need to recompute opaque types and can instead use
|
||||
/// the type_of query to get them from typeck.
|
||||
pub fn reveal_defining_opaque_types(mut self) -> Self {
|
||||
self.reveal_defining_opaque_types = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Given a canonical value `C` as a starting point, create an
|
||||
/// inference context that contains each of the bound values
|
||||
/// within instantiated as a fresh variable. The `f` closure is
|
||||
@ -638,17 +621,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
}
|
||||
|
||||
pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
|
||||
let InferCtxtBuilder {
|
||||
tcx,
|
||||
defining_use_anchor,
|
||||
reveal_defining_opaque_types,
|
||||
ref fresh_typeck_results,
|
||||
} = *self;
|
||||
let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
|
||||
let in_progress_typeck_results = fresh_typeck_results.as_ref();
|
||||
f(InferCtxt {
|
||||
tcx,
|
||||
defining_use_anchor,
|
||||
reveal_defining_opaque_types,
|
||||
in_progress_typeck_results,
|
||||
inner: RefCell::new(InferCtxtInner::new()),
|
||||
lexical_region_resolutions: RefCell::new(None),
|
||||
|
@ -236,11 +236,12 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
SizedBoxType,
|
||||
/// Inline asm operand type must be `Sized`.
|
||||
InlineAsmSized,
|
||||
/// `[T, ..n]` implies that `T` must be `Copy`.
|
||||
/// If the function in the array repeat expression is a `const fn`,
|
||||
/// display a help message suggesting to move the function call to a
|
||||
/// new `const` item while saying that `T` doesn't implement `Copy`.
|
||||
RepeatVec(bool),
|
||||
/// `[expr; N]` requires `type_of(expr): Copy`.
|
||||
RepeatElementCopy {
|
||||
/// If element is a `const fn` we display a help message suggesting to move the
|
||||
/// function call to a new `const` item while saying that `T` doesn't implement `Copy`.
|
||||
is_const_fn: bool,
|
||||
},
|
||||
|
||||
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
|
||||
FieldSized {
|
||||
|
@ -198,7 +198,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
let kind = match pat.kind {
|
||||
hir::PatKind::Wild => PatKind::Wild,
|
||||
|
||||
hir::PatKind::Lit(ref value) => self.lower_lit(value),
|
||||
hir::PatKind::Lit(value) => self.lower_lit(value),
|
||||
|
||||
hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
|
||||
let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
|
||||
|
@ -2285,10 +2285,10 @@ impl<'v> Visitor<'v> for FindTypeParam {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recursive_type_with_infinite_size_error(
|
||||
tcx: TyCtxt<'_>,
|
||||
pub fn recursive_type_with_infinite_size_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
type_def_id: DefId,
|
||||
spans: Vec<Span>,
|
||||
spans: Vec<(Span, Option<hir::HirId>)>,
|
||||
) {
|
||||
assert!(type_def_id.is_local());
|
||||
let span = tcx.hir().span_if_local(type_def_id).unwrap();
|
||||
@ -2297,7 +2297,7 @@ pub fn recursive_type_with_infinite_size_error(
|
||||
let mut err =
|
||||
struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
|
||||
err.span_label(span, "recursive type has infinite size");
|
||||
for &span in &spans {
|
||||
for &(span, _) in &spans {
|
||||
err.span_label(span, "recursive without indirection");
|
||||
}
|
||||
let msg = format!(
|
||||
@ -2305,16 +2305,25 @@ pub fn recursive_type_with_infinite_size_error(
|
||||
path,
|
||||
);
|
||||
if spans.len() <= 4 {
|
||||
// FIXME(compiler-errors): This suggestion might be erroneous if Box is shadowed
|
||||
err.multipart_suggestion(
|
||||
&msg,
|
||||
spans
|
||||
.iter()
|
||||
.flat_map(|&span| {
|
||||
[
|
||||
(span.shrink_to_lo(), "Box<".to_string()),
|
||||
(span.shrink_to_hi(), ">".to_string()),
|
||||
]
|
||||
.into_iter()
|
||||
.into_iter()
|
||||
.flat_map(|(span, field_id)| {
|
||||
if let Some(generic_span) = get_option_generic_from_field_id(tcx, field_id) {
|
||||
// If we match an `Option` and can grab the span of the Option's generic, then
|
||||
// suggest boxing the generic arg for a non-null niche optimization.
|
||||
vec![
|
||||
(generic_span.shrink_to_lo(), "Box<".to_string()),
|
||||
(generic_span.shrink_to_hi(), ">".to_string()),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
(span.shrink_to_lo(), "Box<".to_string()),
|
||||
(span.shrink_to_hi(), ">".to_string()),
|
||||
]
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
Applicability::HasPlaceholders,
|
||||
@ -2325,6 +2334,34 @@ pub fn recursive_type_with_infinite_size_error(
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Extract the span for the generic type `T` of `Option<T>` in a field definition
|
||||
fn get_option_generic_from_field_id(tcx: TyCtxt<'_>, field_id: Option<hir::HirId>) -> Option<Span> {
|
||||
let node = tcx.hir().find(field_id?);
|
||||
|
||||
// Expect a field from our field_id
|
||||
let Some(hir::Node::Field(field_def)) = node
|
||||
else { bug!("Expected HirId corresponding to FieldDef, found: {:?}", node) };
|
||||
|
||||
// Match a type that is a simple QPath with no Self
|
||||
let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = &field_def.ty.kind
|
||||
else { return None };
|
||||
|
||||
// Check if the path we're checking resolves to Option
|
||||
let hir::def::Res::Def(_, did) = path.res
|
||||
else { return None };
|
||||
|
||||
// Bail if this path doesn't describe `::core::option::Option`
|
||||
if !tcx.is_diagnostic_item(sym::Option, did) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Match a single generic arg in the 0th path segment
|
||||
let generic_arg = path.segments.last()?.args?.args.get(0)?;
|
||||
|
||||
// Take the span out of the type, if it's a type
|
||||
if let hir::GenericArg::Type(generic_ty) = generic_arg { Some(generic_ty.span) } else { None }
|
||||
}
|
||||
|
||||
/// Summarizes information
|
||||
#[derive(Clone)]
|
||||
pub enum ArgKind {
|
||||
|
@ -1988,7 +1988,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
ObligationCauseCode::Coercion { source: _, target } => {
|
||||
err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
|
||||
}
|
||||
ObligationCauseCode::RepeatVec(is_const_fn) => {
|
||||
ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
|
||||
err.note(
|
||||
"the `Copy` trait is required because the repeated element will be copied",
|
||||
);
|
||||
|
@ -17,12 +17,20 @@ use std::cmp;
|
||||
pub enum Representability {
|
||||
Representable,
|
||||
ContainsRecursive,
|
||||
SelfRecursive(Vec<Span>),
|
||||
/// Return a list of types that are included in themselves:
|
||||
/// the spans where they are self-included, and (if found)
|
||||
/// the HirId of the FieldDef that defines the self-inclusion.
|
||||
SelfRecursive(Vec<(Span, Option<hir::HirId>)>),
|
||||
}
|
||||
|
||||
/// Check whether a type is representable. This means it cannot contain unboxed
|
||||
/// structural recursion. This check is needed for structs and enums.
|
||||
pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> Representability {
|
||||
pub fn ty_is_representable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
field_id: Option<hir::HirId>,
|
||||
) -> Representability {
|
||||
debug!("is_type_representable: {:?}", ty);
|
||||
// To avoid a stack overflow when checking an enum variant or struct that
|
||||
// contains a different, structurally recursive type, maintain a stack of
|
||||
@ -38,11 +46,12 @@ pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> R
|
||||
let mut force_result = false;
|
||||
let r = is_type_structurally_recursive(
|
||||
tcx,
|
||||
sp,
|
||||
&mut seen,
|
||||
&mut shadow_seen,
|
||||
&mut representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
&mut force_result,
|
||||
);
|
||||
debug!("is_type_representable: {:?} is {:?}", ty, r);
|
||||
@ -61,11 +70,12 @@ fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representabilit
|
||||
|
||||
fn are_inner_types_recursive<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sp: Span,
|
||||
seen: &mut Vec<Ty<'tcx>>,
|
||||
shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
|
||||
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
field_id: Option<hir::HirId>,
|
||||
force_result: &mut bool,
|
||||
) -> Representability {
|
||||
debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen);
|
||||
@ -75,11 +85,12 @@ fn are_inner_types_recursive<'tcx>(
|
||||
fold_repr(fields.iter().map(|ty| {
|
||||
is_type_structurally_recursive(
|
||||
tcx,
|
||||
sp,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
)
|
||||
}))
|
||||
@ -88,20 +99,26 @@ fn are_inner_types_recursive<'tcx>(
|
||||
// FIXME(#11924) Behavior undecided for zero-length vectors.
|
||||
ty::Array(ty, _) => is_type_structurally_recursive(
|
||||
tcx,
|
||||
sp,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
*ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
),
|
||||
ty::Adt(def, substs) => {
|
||||
// Find non representable fields with their spans
|
||||
fold_repr(def.all_fields().map(|field| {
|
||||
let ty = field.ty(tcx, substs);
|
||||
let span = match field.did.as_local().and_then(|id| tcx.hir().find_by_def_id(id)) {
|
||||
Some(hir::Node::Field(field)) => field.ty.span,
|
||||
_ => sp,
|
||||
let (sp, field_id) = match field
|
||||
.did
|
||||
.as_local()
|
||||
.map(|id| tcx.hir().local_def_id_to_hir_id(id))
|
||||
.and_then(|id| tcx.hir().find(id))
|
||||
{
|
||||
Some(hir::Node::Field(field)) => (field.ty.span, Some(field.hir_id)),
|
||||
_ => (sp, field_id),
|
||||
};
|
||||
|
||||
let mut result = None;
|
||||
@ -130,7 +147,7 @@ fn are_inner_types_recursive<'tcx>(
|
||||
// result without adjusting).
|
||||
if shadow_seen.len() > seen.len() && shadow_seen.first() == Some(def) {
|
||||
*force_result = true;
|
||||
result = Some(Representability::SelfRecursive(vec![span]));
|
||||
result = Some(Representability::SelfRecursive(vec![(sp, field_id)]));
|
||||
}
|
||||
|
||||
if result == None {
|
||||
@ -161,16 +178,17 @@ fn are_inner_types_recursive<'tcx>(
|
||||
result = Some(
|
||||
match is_type_structurally_recursive(
|
||||
tcx,
|
||||
span,
|
||||
&mut nested_seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
raw_adt_ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
) {
|
||||
Representability::SelfRecursive(_) => {
|
||||
if *force_result {
|
||||
Representability::SelfRecursive(vec![span])
|
||||
Representability::SelfRecursive(vec![(sp, field_id)])
|
||||
} else {
|
||||
Representability::ContainsRecursive
|
||||
}
|
||||
@ -208,15 +226,16 @@ fn are_inner_types_recursive<'tcx>(
|
||||
result = Some(
|
||||
match is_type_structurally_recursive(
|
||||
tcx,
|
||||
span,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
) {
|
||||
Representability::SelfRecursive(_) => {
|
||||
Representability::SelfRecursive(vec![span])
|
||||
Representability::SelfRecursive(vec![(sp, field_id)])
|
||||
}
|
||||
x => x,
|
||||
},
|
||||
@ -247,29 +266,31 @@ fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
|
||||
// contain any types on stack `seen`?
|
||||
fn is_type_structurally_recursive<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sp: Span,
|
||||
seen: &mut Vec<Ty<'tcx>>,
|
||||
shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
|
||||
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
field_id: Option<hir::HirId>,
|
||||
force_result: &mut bool,
|
||||
) -> Representability {
|
||||
debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp);
|
||||
debug!("is_type_structurally_recursive: {:?} {:?} {:?}", ty, sp, field_id);
|
||||
if let Some(representability) = representable_cache.get(&ty) {
|
||||
debug!(
|
||||
"is_type_structurally_recursive: {:?} {:?} - (cached) {:?}",
|
||||
ty, sp, representability
|
||||
"is_type_structurally_recursive: {:?} {:?} {:?} - (cached) {:?}",
|
||||
ty, sp, field_id, representability
|
||||
);
|
||||
return representability.clone();
|
||||
}
|
||||
|
||||
let representability = is_type_structurally_recursive_inner(
|
||||
tcx,
|
||||
sp,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
);
|
||||
|
||||
@ -279,11 +300,12 @@ fn is_type_structurally_recursive<'tcx>(
|
||||
|
||||
fn is_type_structurally_recursive_inner<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sp: Span,
|
||||
seen: &mut Vec<Ty<'tcx>>,
|
||||
shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
|
||||
representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
field_id: Option<hir::HirId>,
|
||||
force_result: &mut bool,
|
||||
) -> Representability {
|
||||
match ty.kind() {
|
||||
@ -305,7 +327,7 @@ fn is_type_structurally_recursive_inner<'tcx>(
|
||||
if let Some(&seen_adt) = iter.next() {
|
||||
if same_adt(seen_adt, *def) {
|
||||
debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty);
|
||||
return Representability::SelfRecursive(vec![sp]);
|
||||
return Representability::SelfRecursive(vec![(sp, field_id)]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,11 +357,12 @@ fn is_type_structurally_recursive_inner<'tcx>(
|
||||
shadow_seen.push(*def);
|
||||
let out = are_inner_types_recursive(
|
||||
tcx,
|
||||
sp,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
);
|
||||
shadow_seen.pop();
|
||||
@ -350,11 +373,12 @@ fn is_type_structurally_recursive_inner<'tcx>(
|
||||
// No need to push in other cases.
|
||||
are_inner_types_recursive(
|
||||
tcx,
|
||||
sp,
|
||||
seen,
|
||||
shadow_seen,
|
||||
representable_cache,
|
||||
ty,
|
||||
sp,
|
||||
field_id,
|
||||
force_result,
|
||||
)
|
||||
}
|
||||
|
@ -1045,7 +1045,7 @@ pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalD
|
||||
// recursive type. It is only necessary to throw an error on those that
|
||||
// contain themselves. For case 2, there must be an inner type that will be
|
||||
// caught by case 1.
|
||||
match representability::ty_is_representable(tcx, rty, sp) {
|
||||
match representability::ty_is_representable(tcx, rty, sp, None) {
|
||||
Representability::SelfRecursive(spans) => {
|
||||
recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
|
||||
return false;
|
||||
|
@ -95,13 +95,6 @@ impl<'tcx> InheritedBuilder<'tcx> {
|
||||
let def_id = self.def_id;
|
||||
self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
|
||||
}
|
||||
|
||||
/// WF-checking doesn't need to recompute opaque types and can instead use
|
||||
/// the type_of query to get them from typeck.
|
||||
pub fn reveal_defining_opaque_types(mut self) -> Self {
|
||||
self.infcx = self.infcx.reveal_defining_opaque_types();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
||||
|
@ -968,7 +968,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<
|
||||
|
||||
fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> {
|
||||
CheckWfFcxBuilder {
|
||||
inherited: Inherited::build(tcx, def_id).reveal_defining_opaque_types(),
|
||||
inherited: Inherited::build(tcx, def_id),
|
||||
id: hir::HirId::make_owner(def_id),
|
||||
span,
|
||||
param_env: tcx.param_env(def_id),
|
||||
|
@ -84,7 +84,7 @@
|
||||
//! have to change, and is it worse or better now? Would any patterns become truly inexpressible?
|
||||
//! Could we carve out special exceptions for those patterns? Should we?
|
||||
//!
|
||||
//! A secondary goal of this project is to see if we can disamiguate the many functions of
|
||||
//! A secondary goal of this project is to see if we can disambiguate the many functions of
|
||||
//! pointer<->integer casts enough for the definition of `usize` to be loosened so that it
|
||||
//! isn't *pointer*-sized but address-space/offset/allocation-sized (we'll probably continue
|
||||
//! to conflate these notions). This would potentially make it possible to more efficiently
|
||||
@ -163,7 +163,7 @@
|
||||
//! of pointers and `usize` (and `isize`), and defining a pointer to semantically contain the
|
||||
//! following information:
|
||||
//!
|
||||
//! * The **address-space** it is part of (i.e. "data" vs "code" in WASM).
|
||||
//! * The **address-space** it is part of (e.g. "data" vs "code" in WASM).
|
||||
//! * The **address** it points to, which can be represented by a `usize`.
|
||||
//! * The **provenance** it has, defining the memory it has permission to access.
|
||||
//!
|
||||
@ -246,7 +246,7 @@
|
||||
//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers,
|
||||
//! we would like to know why, and what needs to be done to fix it.)
|
||||
//!
|
||||
//! Something more complicated and just generally *evil* like a XOR-List requires more significant
|
||||
//! Something more complicated and just generally *evil* like an XOR-List requires more significant
|
||||
//! changes like allocating all nodes in a pre-allocated Vec or Arena and using a pointer
|
||||
//! to the whole allocation to reconstitute the XORed addresses.
|
||||
//!
|
||||
@ -257,7 +257,7 @@
|
||||
//! special attention at all, because they're generally accessing memory outside the scope of
|
||||
//! "the abstract machine", or already using "I know what I'm doing" annotations like "volatile".
|
||||
//!
|
||||
//! Under [Strict Provenance] is is Undefined Behaviour to:
|
||||
//! Under [Strict Provenance] it is Undefined Behaviour to:
|
||||
//!
|
||||
//! * Access memory through a pointer that does not have provenance over that memory.
|
||||
//!
|
||||
|
@ -65,9 +65,10 @@
|
||||
//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although
|
||||
//! `core` does not.
|
||||
//!
|
||||
//! Currently you'll need to use `#[cfg(target_arch)]` primarily to
|
||||
//! conditionally compile in code with atomics. There is an unstable
|
||||
//! `#[cfg(target_has_atomic)]` as well which may be stabilized in the future.
|
||||
//! The `#[cfg(target_has_atomic)]` attribute can be used to conditionally
|
||||
//! compile based on the target's supported bit widths. It is a key-value
|
||||
//! option set for each supported size, with values "8", "16", "32", "64",
|
||||
//! "128", and "ptr" for pointer-sized atomics.
|
||||
//!
|
||||
//! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm
|
||||
//!
|
||||
|
@ -8,8 +8,8 @@ LL | struct Foo { foo: Option<Option<Foo>> }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | struct Foo { foo: Box<Option<Option<Foo>>> }
|
||||
| ++++ +
|
||||
LL | struct Foo { foo: Option<Box<Option<Foo>>> }
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,8 +8,8 @@ LL | struct Baz { q: Option<Foo> }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
|
||||
|
|
||||
LL | struct Baz { q: Box<Option<Foo>> }
|
||||
| ++++ +
|
||||
LL | struct Baz { q: Option<Box<Foo>> }
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `Foo` has infinite size
|
||||
--> $DIR/issue-17431-2.rs:4:1
|
||||
@ -21,8 +21,8 @@ LL | struct Foo { q: Option<Baz> }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | struct Foo { q: Box<Option<Baz>> }
|
||||
| ++++ +
|
||||
LL | struct Foo { q: Option<Box<Baz>> }
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -8,8 +8,8 @@ LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T>
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
|
||||
| ++++ +
|
||||
LL | struct Foo<T> { foo: Option<Box<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,8 +8,8 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
|
||||
| ++++ +
|
||||
LL | enum Foo { Voo(Option<Box<Option<Foo>>>) }
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,8 +9,8 @@ LL | element: Option<S>
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
|
||||
|
|
||||
LL | element: Box<Option<S>>
|
||||
| ++++ +
|
||||
LL | element: Option<Box<S>>
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,8 +8,8 @@ LL | struct Baz { q: Option<Foo> }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
|
||||
|
|
||||
LL | struct Baz { q: Box<Option<Foo>> }
|
||||
| ++++ +
|
||||
LL | struct Baz { q: Option<Box<Foo>> }
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `Foo` has infinite size
|
||||
--> $DIR/sized-cycle-note.rs:11:1
|
||||
@ -21,8 +21,8 @@ LL | struct Foo { q: Option<Baz> }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | struct Foo { q: Box<Option<Baz>> }
|
||||
| ++++ +
|
||||
LL | struct Foo { q: Option<Box<Baz>> }
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -9,8 +9,8 @@ LL | tail: Option<ListNode>,
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
|
||||
|
|
||||
LL | tail: Box<Option<ListNode>>,
|
||||
| ++++ +
|
||||
LL | tail: Option<Box<ListNode>>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -12,8 +12,8 @@ LL | | }
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
|
||||
|
|
||||
LL | tail: Box<Option<ListNode>>,
|
||||
| ++++ +
|
||||
LL | tail: Option<Box<ListNode>>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -37,8 +37,8 @@ LL | y: Option<Option<D<T>>>,
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `C` representable
|
||||
|
|
||||
LL | y: Box<Option<Option<D<T>>>>,
|
||||
| ++++ +
|
||||
LL | y: Option<Box<Option<D<T>>>>,
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `D` has infinite size
|
||||
--> $DIR/mutual-struct-recursion.rs:18:1
|
||||
@ -51,8 +51,8 @@ LL | z: Option<Option<C<T>>>,
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `D` representable
|
||||
|
|
||||
LL | z: Box<Option<Option<C<T>>>>,
|
||||
| ++++ +
|
||||
LL | z: Option<Box<Option<C<T>>>>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
12
src/test/ui/type/type-recursive-box-shadowed.rs
Normal file
12
src/test/ui/type/type-recursive-box-shadowed.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//FIXME(compiler-errors): This fixup should suggest the full box path, not just `Box`
|
||||
|
||||
struct Box<T> {
|
||||
t: T,
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
//~^ ERROR recursive type `Foo` has infinite size
|
||||
inner: Foo,
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/ui/type/type-recursive-box-shadowed.stderr
Normal file
17
src/test/ui/type/type-recursive-box-shadowed.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0072]: recursive type `Foo` has infinite size
|
||||
--> $DIR/type-recursive-box-shadowed.rs:7:1
|
||||
|
|
||||
LL | struct Foo {
|
||||
| ^^^^^^^^^^ recursive type has infinite size
|
||||
LL |
|
||||
LL | inner: Foo,
|
||||
| --- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | inner: Box<Foo>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0072`.
|
@ -1,6 +1,30 @@
|
||||
struct T1 { //~ ERROR E0072
|
||||
foo: isize,
|
||||
foolish: T1
|
||||
foolish: T1,
|
||||
}
|
||||
|
||||
struct T2 { //~ ERROR E0072
|
||||
inner: Option<T2>,
|
||||
}
|
||||
|
||||
type OptionT3 = Option<T3>;
|
||||
|
||||
struct T3 { //~ ERROR E0072
|
||||
inner: OptionT3,
|
||||
}
|
||||
|
||||
struct T4(Option<T4>); //~ ERROR E0072
|
||||
|
||||
enum T5 { //~ ERROR E0072
|
||||
Variant(Option<T5>),
|
||||
}
|
||||
|
||||
enum T6 { //~ ERROR E0072
|
||||
Variant{ field: Option<T6> },
|
||||
}
|
||||
|
||||
struct T7 { //~ ERROR E0072
|
||||
foo: std::cell::Cell<Option<T7>>,
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -4,14 +4,93 @@ error[E0072]: recursive type `T1` has infinite size
|
||||
LL | struct T1 {
|
||||
| ^^^^^^^^^ recursive type has infinite size
|
||||
LL | foo: isize,
|
||||
LL | foolish: T1
|
||||
LL | foolish: T1,
|
||||
| -- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable
|
||||
|
|
||||
LL | foolish: Box<T1>
|
||||
LL | foolish: Box<T1>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0072]: recursive type `T2` has infinite size
|
||||
--> $DIR/type-recursive.rs:6:1
|
||||
|
|
||||
LL | struct T2 {
|
||||
| ^^^^^^^^^ recursive type has infinite size
|
||||
LL | inner: Option<T2>,
|
||||
| ---------- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T2` representable
|
||||
|
|
||||
LL | inner: Option<Box<T2>>,
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `T3` has infinite size
|
||||
--> $DIR/type-recursive.rs:12:1
|
||||
|
|
||||
LL | struct T3 {
|
||||
| ^^^^^^^^^ recursive type has infinite size
|
||||
LL | inner: OptionT3,
|
||||
| -------- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T3` representable
|
||||
|
|
||||
LL | inner: Box<OptionT3>,
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `T4` has infinite size
|
||||
--> $DIR/type-recursive.rs:16:1
|
||||
|
|
||||
LL | struct T4(Option<T4>);
|
||||
| ^^^^^^^^^^----------^^
|
||||
| | |
|
||||
| | recursive without indirection
|
||||
| recursive type has infinite size
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T4` representable
|
||||
|
|
||||
LL | struct T4(Option<Box<T4>>);
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `T5` has infinite size
|
||||
--> $DIR/type-recursive.rs:18:1
|
||||
|
|
||||
LL | enum T5 {
|
||||
| ^^^^^^^ recursive type has infinite size
|
||||
LL | Variant(Option<T5>),
|
||||
| ---------- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T5` representable
|
||||
|
|
||||
LL | Variant(Option<Box<T5>>),
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `T6` has infinite size
|
||||
--> $DIR/type-recursive.rs:22:1
|
||||
|
|
||||
LL | enum T6 {
|
||||
| ^^^^^^^ recursive type has infinite size
|
||||
LL | Variant{ field: Option<T6> },
|
||||
| ---------- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T6` representable
|
||||
|
|
||||
LL | Variant{ field: Option<Box<T6>> },
|
||||
| ++++ +
|
||||
|
||||
error[E0072]: recursive type `T7` has infinite size
|
||||
--> $DIR/type-recursive.rs:26:1
|
||||
|
|
||||
LL | struct T7 {
|
||||
| ^^^^^^^^^ recursive type has infinite size
|
||||
LL | foo: std::cell::Cell<Option<T7>>,
|
||||
| --------------------------- recursive without indirection
|
||||
|
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T7` representable
|
||||
|
|
||||
LL | foo: Box<std::cell::Cell<Option<T7>>>,
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0072`.
|
||||
|
Loading…
Reference in New Issue
Block a user