mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
Merge from rustc
This commit is contained in:
commit
13dbc8443e
@ -111,9 +111,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.17"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
|
@ -670,13 +670,6 @@ Cargo
|
||||
- [Support `target.<triple>.rustdocflags` officially](https://github.com/rust-lang/cargo/pull/13197/)
|
||||
- [Stabilize global cache data tracking](https://github.com/rust-lang/cargo/pull/13492/)
|
||||
|
||||
<a id="1.78.0-Misc"></a>
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
- [rustdoc: add `--test-builder-wrapper` arg to support wrappers such as RUSTC_WRAPPER when building doctests](https://github.com/rust-lang/rust/pull/114651/)
|
||||
|
||||
<a id="1.78.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
|
@ -2052,6 +2052,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Used when lowering a type argument that turned out to actually be a const argument.
|
||||
///
|
||||
/// Only use for that purpose since otherwise it will create a duplicate def.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_const_path_to_const_arg(
|
||||
&mut self,
|
||||
@ -2060,51 +2063,58 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
ty_id: NodeId,
|
||||
span: Span,
|
||||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let ct_kind = match res {
|
||||
Res::Def(DefKind::ConstParam, _) => {
|
||||
let qpath = self.lower_qpath(
|
||||
ty_id,
|
||||
&None,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
AllowReturnTypeNotation::No,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
hir::ConstArgKind::Path(qpath)
|
||||
}
|
||||
_ => {
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
let tcx = self.tcx;
|
||||
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(span);
|
||||
// FIXME(min_generic_const_args): we only allow one-segment const paths for now
|
||||
let ct_kind = if path.is_potential_trivial_const_arg()
|
||||
&& (tcx.features().min_generic_const_args()
|
||||
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
|
||||
{
|
||||
let qpath = self.lower_qpath(
|
||||
ty_id,
|
||||
&None,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
AllowReturnTypeNotation::No,
|
||||
// FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
hir::ConstArgKind::Path(qpath)
|
||||
} else {
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
let def_id =
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(span);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty_id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
// Add a definition for the in-band const def.
|
||||
// We're lowering a const argument that was originally thought to be a type argument,
|
||||
// so the def collector didn't create the def ahead of time. That's why we have to do
|
||||
// it here.
|
||||
let def_id =
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty_id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||
}),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||
}),
|
||||
span,
|
||||
})
|
||||
});
|
||||
hir::ConstArgKind::Anon(ct)
|
||||
}
|
||||
})
|
||||
});
|
||||
hir::ConstArgKind::Anon(ct)
|
||||
};
|
||||
|
||||
self.arena.alloc(hir::ConstArg {
|
||||
@ -2122,6 +2132,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
||||
let tcx = self.tcx;
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
||||
@ -2135,18 +2146,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
};
|
||||
let maybe_res =
|
||||
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
||||
debug!("res={:?}", maybe_res);
|
||||
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
|
||||
if let Some(res) = maybe_res
|
||||
&& let Res::Def(DefKind::ConstParam, _) = res
|
||||
&& let ExprKind::Path(qself, path) = &expr.kind
|
||||
// FIXME(min_generic_const_args): we only allow one-segment const paths for now
|
||||
if let ExprKind::Path(None, path) = &expr.kind
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
&& (tcx.features().min_generic_const_args()
|
||||
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
|
||||
{
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
qself,
|
||||
&None,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
AllowReturnTypeNotation::No,
|
||||
// FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
@ -18,7 +18,6 @@
|
||||
pub mod ast_validation;
|
||||
mod errors;
|
||||
pub mod feature_gate;
|
||||
pub mod node_count;
|
||||
pub mod show_span;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
@ -1,129 +0,0 @@
|
||||
// Simply gives a rough count of the number of nodes in an AST.
|
||||
|
||||
use rustc_ast::visit::*;
|
||||
use rustc_ast::*;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
pub struct NodeCounter {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl NodeCounter {
|
||||
pub fn new() -> NodeCounter {
|
||||
NodeCounter { count: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Visitor<'ast> for NodeCounter {
|
||||
fn visit_ident(&mut self, _ident: &Ident) {
|
||||
self.count += 1;
|
||||
}
|
||||
fn visit_foreign_item(&mut self, i: &ForeignItem) {
|
||||
self.count += 1;
|
||||
walk_item(self, i)
|
||||
}
|
||||
fn visit_item(&mut self, i: &Item) {
|
||||
self.count += 1;
|
||||
walk_item(self, i)
|
||||
}
|
||||
fn visit_local(&mut self, l: &Local) {
|
||||
self.count += 1;
|
||||
walk_local(self, l)
|
||||
}
|
||||
fn visit_block(&mut self, b: &Block) {
|
||||
self.count += 1;
|
||||
walk_block(self, b)
|
||||
}
|
||||
fn visit_stmt(&mut self, s: &Stmt) {
|
||||
self.count += 1;
|
||||
walk_stmt(self, s)
|
||||
}
|
||||
fn visit_arm(&mut self, a: &Arm) {
|
||||
self.count += 1;
|
||||
walk_arm(self, a)
|
||||
}
|
||||
fn visit_pat(&mut self, p: &Pat) {
|
||||
self.count += 1;
|
||||
walk_pat(self, p)
|
||||
}
|
||||
fn visit_expr(&mut self, ex: &Expr) {
|
||||
self.count += 1;
|
||||
walk_expr(self, ex)
|
||||
}
|
||||
fn visit_ty(&mut self, t: &Ty) {
|
||||
self.count += 1;
|
||||
walk_ty(self, t)
|
||||
}
|
||||
fn visit_generic_param(&mut self, param: &GenericParam) {
|
||||
self.count += 1;
|
||||
walk_generic_param(self, param)
|
||||
}
|
||||
fn visit_generics(&mut self, g: &Generics) {
|
||||
self.count += 1;
|
||||
walk_generics(self, g)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'_>, _: Span, _: NodeId) {
|
||||
self.count += 1;
|
||||
walk_fn(self, fk)
|
||||
}
|
||||
fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) {
|
||||
self.count += 1;
|
||||
walk_assoc_item(self, ti, ctxt);
|
||||
}
|
||||
fn visit_trait_ref(&mut self, t: &TraitRef) {
|
||||
self.count += 1;
|
||||
walk_trait_ref(self, t)
|
||||
}
|
||||
fn visit_param_bound(&mut self, bounds: &GenericBound, _ctxt: BoundKind) {
|
||||
self.count += 1;
|
||||
walk_param_bound(self, bounds)
|
||||
}
|
||||
fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef) {
|
||||
self.count += 1;
|
||||
walk_poly_trait_ref(self, t)
|
||||
}
|
||||
fn visit_variant_data(&mut self, s: &VariantData) {
|
||||
self.count += 1;
|
||||
walk_struct_def(self, s)
|
||||
}
|
||||
fn visit_field_def(&mut self, s: &FieldDef) {
|
||||
self.count += 1;
|
||||
walk_field_def(self, s)
|
||||
}
|
||||
fn visit_enum_def(&mut self, enum_definition: &EnumDef) {
|
||||
self.count += 1;
|
||||
walk_enum_def(self, enum_definition)
|
||||
}
|
||||
fn visit_variant(&mut self, v: &Variant) {
|
||||
self.count += 1;
|
||||
walk_variant(self, v)
|
||||
}
|
||||
fn visit_lifetime(&mut self, lifetime: &Lifetime, _: visit::LifetimeCtxt) {
|
||||
self.count += 1;
|
||||
walk_lifetime(self, lifetime)
|
||||
}
|
||||
fn visit_mac_call(&mut self, mac: &MacCall) {
|
||||
self.count += 1;
|
||||
walk_mac(self, mac)
|
||||
}
|
||||
fn visit_path(&mut self, path: &Path, _id: NodeId) {
|
||||
self.count += 1;
|
||||
walk_path(self, path)
|
||||
}
|
||||
fn visit_use_tree(&mut self, use_tree: &UseTree, id: NodeId, _nested: bool) {
|
||||
self.count += 1;
|
||||
walk_use_tree(self, use_tree, id)
|
||||
}
|
||||
fn visit_generic_args(&mut self, generic_args: &GenericArgs) {
|
||||
self.count += 1;
|
||||
walk_generic_args(self, generic_args)
|
||||
}
|
||||
fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint) {
|
||||
self.count += 1;
|
||||
walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
fn visit_attribute(&mut self, _attr: &Attribute) {
|
||||
self.count += 1;
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
||||
UniverseInfo::RelateTys { expected, found } => {
|
||||
let err = mbcx.infcx.err_ctxt().report_mismatched_types(
|
||||
&cause,
|
||||
mbcx.param_env,
|
||||
mbcx.infcx.param_env,
|
||||
expected,
|
||||
found,
|
||||
TypeError::RegionsPlaceholderMismatch,
|
||||
|
@ -266,7 +266,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if self.param_env.caller_bounds().iter().any(|c| {
|
||||
if self.infcx.param_env.caller_bounds().iter().any(|c| {
|
||||
c.as_trait_clause().is_some_and(|pred| {
|
||||
pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id())
|
||||
})
|
||||
@ -682,13 +682,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
// Normalize before comparing to see through type aliases and projections.
|
||||
let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args);
|
||||
let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args);
|
||||
if let Ok(old_ty) =
|
||||
tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), old_ty)
|
||||
&& let Ok(new_ty) = tcx.try_normalize_erasing_regions(
|
||||
self.infcx.typing_env(self.param_env),
|
||||
new_ty,
|
||||
)
|
||||
{
|
||||
if let Ok(old_ty) = tcx.try_normalize_erasing_regions(
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
old_ty,
|
||||
) && let Ok(new_ty) = tcx.try_normalize_erasing_regions(
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
new_ty,
|
||||
) {
|
||||
old_ty == new_ty
|
||||
} else {
|
||||
false
|
||||
@ -707,15 +707,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
// Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
|
||||
clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
|
||||
// Normalize before testing to see through type aliases and projections.
|
||||
if let Ok(normalized) =
|
||||
tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), clause)
|
||||
{
|
||||
if let Ok(normalized) = tcx.try_normalize_erasing_regions(
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
clause,
|
||||
) {
|
||||
clause = normalized;
|
||||
}
|
||||
self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
clause,
|
||||
))
|
||||
})
|
||||
@ -904,7 +905,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
|
||||
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
|
||||
|
||||
let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
|
||||
let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.infcx.param_env, ty)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
@ -1304,7 +1305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
|
||||
let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
|
||||
self.infcx
|
||||
.type_implements_trait(clone_trait_def, [ty], self.param_env)
|
||||
.type_implements_trait(clone_trait_def, [ty], self.infcx.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
}
|
||||
|
||||
@ -1437,7 +1438,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
|
||||
let cause = ObligationCause::misc(span, self.mir_def_id());
|
||||
|
||||
ocx.register_bound(cause, self.param_env, ty, def_id);
|
||||
ocx.register_bound(cause, self.infcx.param_env, ty, def_id);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
// Only emit suggestion if all required predicates are on generic
|
||||
@ -1957,7 +1958,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
&& let ty::Ref(_, inner, _) = rcvr_ty.kind()
|
||||
&& let inner = inner.peel_refs()
|
||||
&& (Holds { ty: inner }).visit_ty(local_ty).is_break()
|
||||
&& let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
|
||||
&& let None =
|
||||
self.infcx.type_implements_trait_shallow(clone, inner, self.infcx.param_env)
|
||||
{
|
||||
err.span_label(
|
||||
span,
|
||||
@ -1989,7 +1991,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
trait_ref,
|
||||
);
|
||||
self.infcx.err_ctxt().suggest_derive(
|
||||
@ -3398,7 +3400,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
|
||||
&& self
|
||||
.infcx
|
||||
.type_implements_trait(iter_trait, [return_ty], self.param_env)
|
||||
.type_implements_trait(iter_trait, [return_ty], self.infcx.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
err.span_suggestion_hidden(
|
||||
@ -3839,14 +3841,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
|
||||
Instance::try_resolve(
|
||||
tcx,
|
||||
self.infcx.typing_env(self.param_env),
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
deref_target,
|
||||
method_args,
|
||||
)
|
||||
.transpose()
|
||||
});
|
||||
if let Some(Ok(instance)) = deref_target {
|
||||
let deref_target_ty = instance.ty(tcx, self.infcx.typing_env(self.param_env));
|
||||
let deref_target_ty =
|
||||
instance.ty(tcx, self.infcx.typing_env(self.infcx.param_env));
|
||||
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
|
||||
err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
|
||||
let kind = call_kind(
|
||||
self.infcx.tcx,
|
||||
self.infcx.typing_env(self.param_env),
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
method_did,
|
||||
method_args,
|
||||
*fn_span,
|
||||
@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
|
||||
Some(def_id) => type_known_to_meet_bound_modulo_regions(
|
||||
self.infcx,
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
|
||||
def_id,
|
||||
),
|
||||
@ -1224,7 +1224,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
BoundRegionConversionTime::FnCall,
|
||||
tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0),
|
||||
)
|
||||
&& self.infcx.can_eq(self.param_env, ty, self_ty)
|
||||
&& self.infcx.can_eq(self.infcx.param_env, ty, self_ty)
|
||||
{
|
||||
err.subdiagnostic(CaptureReasonSuggest::FreshReborrow {
|
||||
span: move_span.shrink_to_hi(),
|
||||
@ -1258,7 +1258,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
if let Some(errors) = self.infcx.type_implements_trait_shallow(
|
||||
clone_trait,
|
||||
ty,
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
) && !has_sugg
|
||||
{
|
||||
let msg = match &errors[..] {
|
||||
|
@ -305,7 +305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
|
||||
// This is only going to be ambiguous if there are incoherent impls, because otherwise
|
||||
// ambiguity should never happen in MIR.
|
||||
self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
|
||||
self.infcx.type_implements_trait(copy_trait_def, [ty], self.infcx.param_env).may_apply()
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
|
@ -1242,7 +1242,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
.type_implements_trait_shallow(
|
||||
clone_trait,
|
||||
ty.peel_refs(),
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
)
|
||||
.as_deref()
|
||||
{
|
||||
@ -1279,7 +1279,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let obligation = traits::Obligation::new(
|
||||
self.infcx.tcx,
|
||||
traits::ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
self.infcx.param_env,
|
||||
trait_ref,
|
||||
);
|
||||
self.infcx.err_ctxt().suggest_derive(
|
||||
|
@ -952,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
|
||||
if let Ok(Some(instance)) = ty::Instance::try_resolve(
|
||||
tcx,
|
||||
self.infcx.typing_env(self.param_env),
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
*fn_did,
|
||||
self.infcx.resolve_vars_if_possible(args),
|
||||
) {
|
||||
@ -1091,7 +1091,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
peeled_ty = ref_ty;
|
||||
count += 1;
|
||||
}
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.infcx.param_env, peeled_ty) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let ocx = ObligationCtxt::new(&self.infcx);
|
||||
ocx.register_obligations(preds.iter().map(|(pred, span)| {
|
||||
trace!(?pred);
|
||||
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
|
||||
Obligation::misc(tcx, span, self.mir_def_id(), self.infcx.param_env, pred)
|
||||
}));
|
||||
|
||||
if ocx.select_all_or_error().is_empty() && count > 0 {
|
||||
|
@ -140,7 +140,6 @@ fn do_mir_borrowck<'tcx>(
|
||||
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
|
||||
let def = input_body.source.def_id().expect_local();
|
||||
let infcx = BorrowckInferCtxt::new(tcx, def);
|
||||
let param_env = tcx.param_env(def);
|
||||
|
||||
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
|
||||
for var_debug_info in &input_body.var_debug_info {
|
||||
@ -175,8 +174,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
// will have a lifetime tied to the inference context.
|
||||
let mut body_owned = input_body.clone();
|
||||
let mut promoted = input_promoted.to_owned();
|
||||
let free_regions =
|
||||
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
|
||||
let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
|
||||
let body = &body_owned; // no further changes
|
||||
|
||||
// FIXME(-Znext-solver): A bit dubious that we're only registering
|
||||
@ -192,7 +190,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
.iter_enumerated()
|
||||
.map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
|
||||
|
||||
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||
.iterate_to_fixpoint(tcx, body, Some("borrowck"))
|
||||
.into_results_cursor(body);
|
||||
|
||||
@ -213,18 +211,12 @@ fn do_mir_borrowck<'tcx>(
|
||||
body,
|
||||
&promoted,
|
||||
&location_table,
|
||||
param_env,
|
||||
&mut flow_inits,
|
||||
flow_inits,
|
||||
&move_data,
|
||||
&borrow_set,
|
||||
tcx.closure_captures(def),
|
||||
consumer_options,
|
||||
);
|
||||
|
||||
// `flow_inits` is large, so we drop it as soon as possible. This reduces
|
||||
// peak memory usage significantly on some benchmarks.
|
||||
drop(flow_inits);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This let us
|
||||
// write unit-tests, as well as helping with debugging.
|
||||
nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set);
|
||||
@ -251,7 +243,6 @@ fn do_mir_borrowck<'tcx>(
|
||||
let promoted_body = &promoted[idx];
|
||||
let mut promoted_mbcx = MirBorrowckCtxt {
|
||||
infcx: &infcx,
|
||||
param_env,
|
||||
body: promoted_body,
|
||||
move_data: &move_data,
|
||||
location_table: &location_table, // no need to create a real one for the promoted, it is not used
|
||||
@ -291,7 +282,6 @@ fn do_mir_borrowck<'tcx>(
|
||||
|
||||
let mut mbcx = MirBorrowckCtxt {
|
||||
infcx: &infcx,
|
||||
param_env,
|
||||
body,
|
||||
move_data: &move_data,
|
||||
location_table: &location_table,
|
||||
@ -448,12 +438,14 @@ fn get_flow_results<'a, 'tcx>(
|
||||
pub(crate) struct BorrowckInferCtxt<'tcx> {
|
||||
pub(crate) infcx: InferCtxt<'tcx>,
|
||||
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
|
||||
pub(crate) param_env: ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> BorrowckInferCtxt<'tcx> {
|
||||
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
|
||||
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
|
||||
let param_env = tcx.param_env(def_id);
|
||||
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
|
||||
}
|
||||
|
||||
pub(crate) fn next_region_var<F>(
|
||||
@ -532,7 +524,6 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
|
||||
|
||||
struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
|
||||
|
@ -30,7 +30,7 @@ use crate::diagnostics::RegionErrors;
|
||||
use crate::facts::{AllFacts, AllFactsExt, RustcFacts};
|
||||
use crate::location::LocationTable;
|
||||
use crate::region_infer::RegionInferenceContext;
|
||||
use crate::type_check::{self, MirTypeckRegionConstraints, MirTypeckResults};
|
||||
use crate::type_check::{self, MirTypeckResults};
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
use crate::{BorrowckInferCtxt, polonius, renumber};
|
||||
|
||||
@ -50,10 +50,9 @@ pub(crate) struct NllOutput<'tcx> {
|
||||
/// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
|
||||
/// regions (e.g., region parameters) declared on the function. That set will need to be given to
|
||||
/// `compute_regions`.
|
||||
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
|
||||
#[instrument(skip(infcx, body, promoted), level = "debug")]
|
||||
pub(crate) fn replace_regions_in_mir<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
|
||||
) -> UniversalRegions<'tcx> {
|
||||
@ -62,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
|
||||
debug!(?def);
|
||||
|
||||
// Compute named region information. This also renumbers the inputs/outputs.
|
||||
let universal_regions = UniversalRegions::new(infcx, def, param_env);
|
||||
let universal_regions = UniversalRegions::new(infcx, def);
|
||||
|
||||
// Replace all remaining regions with fresh inference variables.
|
||||
renumber::renumber_mir(infcx, body, promoted);
|
||||
@ -81,11 +80,9 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
location_table: &LocationTable,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
consumer_options: Option<ConsumerOptions>,
|
||||
) -> NllOutput<'tcx> {
|
||||
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
|
||||
@ -96,41 +93,27 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||
let mut all_facts =
|
||||
(polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
|
||||
|
||||
let universal_regions = Rc::new(universal_regions);
|
||||
|
||||
let elements = Rc::new(DenseLocationMap::new(body));
|
||||
|
||||
// Run the MIR type-checker.
|
||||
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
|
||||
type_check::type_check(
|
||||
infcx,
|
||||
param_env,
|
||||
body,
|
||||
promoted,
|
||||
Rc::clone(&universal_regions),
|
||||
universal_regions,
|
||||
location_table,
|
||||
borrow_set,
|
||||
&mut all_facts,
|
||||
flow_inits,
|
||||
move_data,
|
||||
Rc::clone(&elements),
|
||||
upvars,
|
||||
);
|
||||
|
||||
// Create the region inference context, taking ownership of the
|
||||
// region inference data that was contained in `infcx`, and the
|
||||
// base constraints generated by the type-check.
|
||||
let var_origins = infcx.get_region_var_origins();
|
||||
let MirTypeckRegionConstraints {
|
||||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
liveness_constraints,
|
||||
mut outlives_constraints,
|
||||
mut member_constraints,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
let placeholder_indices = Rc::new(placeholder_indices);
|
||||
|
||||
// If requested, emit legacy polonius facts.
|
||||
polonius::emit_facts(
|
||||
@ -140,31 +123,14 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||
body,
|
||||
borrow_set,
|
||||
move_data,
|
||||
&universal_regions,
|
||||
&universal_region_relations,
|
||||
);
|
||||
|
||||
if let Some(guar) = universal_regions.tainted_by_errors() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
|
||||
// outlives bounds that we may end up checking.
|
||||
outlives_constraints = Default::default();
|
||||
member_constraints = Default::default();
|
||||
|
||||
// Also taint the entire scope.
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
let mut regioncx = RegionInferenceContext::new(
|
||||
infcx,
|
||||
var_origins,
|
||||
universal_regions,
|
||||
placeholder_indices,
|
||||
constraints,
|
||||
universal_region_relations,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
liveness_constraints,
|
||||
elements,
|
||||
);
|
||||
|
||||
|
@ -12,7 +12,6 @@ use crate::borrow_set::BorrowSet;
|
||||
use crate::facts::{AllFacts, PoloniusRegionVid};
|
||||
use crate::location::LocationTable;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
mod loan_invalidations;
|
||||
mod loan_kills;
|
||||
@ -32,7 +31,6 @@ pub(crate) fn emit_facts<'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
move_data: &MoveData<'_>,
|
||||
universal_regions: &UniversalRegions<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
let Some(all_facts) = all_facts else {
|
||||
@ -41,12 +39,7 @@ pub(crate) fn emit_facts<'tcx>(
|
||||
};
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
emit_move_facts(all_facts, move_data, location_table, body);
|
||||
emit_universal_region_facts(
|
||||
all_facts,
|
||||
borrow_set,
|
||||
universal_regions,
|
||||
universal_region_relations,
|
||||
);
|
||||
emit_universal_region_facts(all_facts, borrow_set, universal_region_relations);
|
||||
emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
}
|
||||
@ -129,7 +122,6 @@ fn emit_move_facts(
|
||||
fn emit_universal_region_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
borrow_set: &BorrowSet<'_>,
|
||||
universal_regions: &UniversalRegions<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
// 1: universal regions are modeled in Polonius as a pair:
|
||||
@ -138,9 +130,10 @@ fn emit_universal_region_facts(
|
||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||
// added to the existing number of loans, as if they succeeded them in the set.
|
||||
//
|
||||
let universal_regions = &universal_region_relations.universal_regions;
|
||||
all_facts
|
||||
.universal_region
|
||||
.extend(universal_regions.universal_regions().map(PoloniusRegionVid::from));
|
||||
.extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
|
||||
let borrow_count = borrow_set.len();
|
||||
debug!(
|
||||
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
||||
@ -148,7 +141,7 @@ fn emit_universal_region_facts(
|
||||
borrow_count
|
||||
);
|
||||
|
||||
for universal_region in universal_regions.universal_regions() {
|
||||
for universal_region in universal_regions.universal_regions_iter() {
|
||||
let universal_region_idx = universal_region.index();
|
||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||
all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
|
||||
|
@ -23,7 +23,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
for region in self.regions() {
|
||||
if let NllRegionVariableOrigin::FreeRegion = self.definitions[region].origin {
|
||||
let classification = self.universal_regions.region_classification(region).unwrap();
|
||||
let classification =
|
||||
self.universal_regions().region_classification(region).unwrap();
|
||||
let outlived_by = self.universal_region_relations.regions_outlived_by(region);
|
||||
writeln!(
|
||||
out,
|
||||
|
@ -31,11 +31,9 @@ use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
|
||||
use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
|
||||
use crate::nll::PoloniusOutput;
|
||||
use crate::region_infer::reverse_sccs::ReverseSccGraph;
|
||||
use crate::region_infer::values::{
|
||||
LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
|
||||
};
|
||||
use crate::type_check::Locations;
|
||||
use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex};
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::type_check::{Locations, MirTypeckRegionConstraints};
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
mod dump_mir;
|
||||
@ -191,10 +189,6 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
/// Type constraints that we check after solving.
|
||||
type_tests: Vec<TypeTest<'tcx>>,
|
||||
|
||||
/// Information about the universally quantified regions in scope
|
||||
/// on this function.
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
|
||||
/// Information about how the universally quantified regions in
|
||||
/// scope on this function relate to one another.
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
@ -399,21 +393,36 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn new(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
var_infos: VarInfos,
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
placeholder_indices: Rc<PlaceholderIndices>,
|
||||
constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
mut outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||
type_tests: Vec<TypeTest<'tcx>>,
|
||||
liveness_constraints: LivenessValues,
|
||||
elements: Rc<DenseLocationMap>,
|
||||
) -> Self {
|
||||
debug!("universal_regions: {:#?}", universal_regions);
|
||||
let universal_regions = &universal_region_relations.universal_regions;
|
||||
let MirTypeckRegionConstraints {
|
||||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
liveness_constraints,
|
||||
mut outlives_constraints,
|
||||
mut member_constraints,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
|
||||
debug!("universal_regions: {:#?}", universal_region_relations.universal_regions);
|
||||
debug!("outlives constraints: {:#?}", outlives_constraints);
|
||||
debug!("placeholder_indices: {:#?}", placeholder_indices);
|
||||
debug!("type tests: {:#?}", type_tests);
|
||||
|
||||
if let Some(guar) = universal_region_relations.universal_regions.tainted_by_errors() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
|
||||
// outlives bounds that we may end up checking.
|
||||
outlives_constraints = Default::default();
|
||||
member_constraints = Default::default();
|
||||
|
||||
// Also taint the entire scope.
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
// Create a RegionDefinition for each inference variable.
|
||||
let definitions: IndexVec<_, _> = var_infos
|
||||
.iter()
|
||||
@ -438,7 +447,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
|
||||
let member_constraints =
|
||||
Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
|
||||
Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r)));
|
||||
|
||||
let mut result = Self {
|
||||
var_infos,
|
||||
@ -453,7 +462,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
universe_causes,
|
||||
scc_values,
|
||||
type_tests,
|
||||
universal_regions,
|
||||
universal_region_relations,
|
||||
};
|
||||
|
||||
@ -518,7 +526,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn init_free_and_bound_regions(&mut self) {
|
||||
// Update the names (if any)
|
||||
// This iterator has unstable order but we collect it all into an IndexVec
|
||||
for (external_name, variable) in self.universal_regions.named_universal_regions() {
|
||||
for (external_name, variable) in
|
||||
self.universal_region_relations.universal_regions.named_universal_regions_iter()
|
||||
{
|
||||
debug!(
|
||||
"init_free_and_bound_regions: region {:?} has external name {:?}",
|
||||
variable, external_name
|
||||
@ -562,7 +572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
///
|
||||
/// (Panics if `r` is not a registered universal region.)
|
||||
pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
self.universal_regions.to_region_vid(r)
|
||||
self.universal_regions().to_region_vid(r)
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the outlives constraints.
|
||||
@ -574,7 +584,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
/// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
|
||||
pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
|
||||
self.universal_regions.annotate(tcx, err)
|
||||
self.universal_regions().annotate(tcx, err)
|
||||
}
|
||||
|
||||
/// Returns `true` if the region `r` contains the point `p`.
|
||||
@ -686,7 +696,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
if outlives_requirements.is_empty() {
|
||||
(None, errors_buffer)
|
||||
} else {
|
||||
let num_external_vids = self.universal_regions.num_global_and_external_regions();
|
||||
let num_external_vids = self.universal_regions().num_global_and_external_regions();
|
||||
(
|
||||
Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
|
||||
errors_buffer,
|
||||
@ -989,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// always be in the root universe.
|
||||
if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() {
|
||||
debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p);
|
||||
let static_r = self.universal_regions.fr_static;
|
||||
let static_r = self.universal_regions().fr_static;
|
||||
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
||||
subject,
|
||||
outlived_free_region: static_r,
|
||||
@ -1032,8 +1042,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// avoid potential non-determinism we approximate this by requiring
|
||||
// T: '1 and T: '2.
|
||||
for upper_bound in non_local_ub {
|
||||
debug_assert!(self.universal_regions.is_universal_region(upper_bound));
|
||||
debug_assert!(!self.universal_regions.is_local_free_region(upper_bound));
|
||||
debug_assert!(self.universal_regions().is_universal_region(upper_bound));
|
||||
debug_assert!(!self.universal_regions().is_local_free_region(upper_bound));
|
||||
|
||||
let requirement = ClosureOutlivesRequirement {
|
||||
subject,
|
||||
@ -1101,7 +1111,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// To do so, we simply check every candidate `u_r` for equality.
|
||||
self.scc_values
|
||||
.universal_regions_outlived_by(r_scc)
|
||||
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
|
||||
.filter(|&u_r| !self.universal_regions().is_local_free_region(u_r))
|
||||
.find(|&u_r| self.eval_equal(u_r, r_vid))
|
||||
.map(|u_r| ty::Region::new_var(tcx, u_r))
|
||||
// In case we could not find a named region to map to,
|
||||
@ -1139,9 +1149,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
// Find the smallest universal region that contains all other
|
||||
// universal regions within `region`.
|
||||
let mut lub = self.universal_regions.fr_fn_body;
|
||||
let mut lub = self.universal_regions().fr_fn_body;
|
||||
let r_scc = self.constraint_sccs.scc(r);
|
||||
let static_r = self.universal_regions.fr_static;
|
||||
let static_r = self.universal_regions().fr_static;
|
||||
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
|
||||
let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
|
||||
debug!(?ur, ?lub, ?new_lub);
|
||||
@ -1288,12 +1298,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
debug!(
|
||||
"sup_region's value = {:?} universal={:?}",
|
||||
self.region_value_str(sup_region),
|
||||
self.universal_regions.is_universal_region(sup_region),
|
||||
self.universal_regions().is_universal_region(sup_region),
|
||||
);
|
||||
debug!(
|
||||
"sub_region's value = {:?} universal={:?}",
|
||||
self.region_value_str(sub_region),
|
||||
self.universal_regions.is_universal_region(sub_region),
|
||||
self.universal_regions().is_universal_region(sub_region),
|
||||
);
|
||||
|
||||
let sub_region_scc = self.constraint_sccs.scc(sub_region);
|
||||
@ -1308,7 +1318,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
by super `{sup_region_scc:?}`, promoting to static",
|
||||
);
|
||||
|
||||
return self.eval_outlives(sup_region, self.universal_regions.fr_static);
|
||||
return self.eval_outlives(sup_region, self.universal_regions().fr_static);
|
||||
}
|
||||
|
||||
// Both the `sub_region` and `sup_region` consist of the union
|
||||
@ -1332,7 +1342,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// Now we have to compare all the points in the sub region and make
|
||||
// sure they exist in the sup region.
|
||||
|
||||
if self.universal_regions.is_universal_region(sup_region) {
|
||||
if self.universal_regions().is_universal_region(sup_region) {
|
||||
// Micro-opt: universal regions contain all points.
|
||||
debug!("super is universal and hence contains all points");
|
||||
return true;
|
||||
@ -1736,7 +1746,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
|
||||
let result = {
|
||||
r == fr2 || {
|
||||
fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
|
||||
fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
|
||||
}
|
||||
};
|
||||
debug!("provides_universal_region: result = {:?}", result);
|
||||
@ -1837,7 +1847,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
// A constraint like `'r: 'x` can come from our constraint
|
||||
// graph.
|
||||
let fr_static = self.universal_regions.fr_static;
|
||||
let fr_static = self.universal_regions().fr_static;
|
||||
let outgoing_edges_from_graph =
|
||||
self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
|
||||
|
||||
@ -1952,7 +1962,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> {
|
||||
self.universal_regions.as_ref()
|
||||
&self.universal_region_relations.universal_regions
|
||||
}
|
||||
|
||||
/// Tries to find the best constraint to blame for the fact that
|
||||
@ -2212,7 +2222,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
/// Access to the region graph, built from the outlives constraints.
|
||||
pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> {
|
||||
self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static)
|
||||
self.constraint_graph.region_graph(&self.constraints, self.universal_regions().fr_static)
|
||||
}
|
||||
|
||||
/// Returns whether the given region is considered live at all points: whether it is a
|
||||
|
@ -74,7 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
debug!(?opaque_type_key, ?concrete_type);
|
||||
|
||||
let mut arg_regions: Vec<(ty::RegionVid, ty::Region<'_>)> =
|
||||
vec![(self.universal_regions.fr_static, infcx.tcx.lifetimes.re_static)];
|
||||
vec![(self.universal_regions().fr_static, infcx.tcx.lifetimes.re_static)];
|
||||
|
||||
let opaque_type_key =
|
||||
opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| {
|
||||
@ -88,12 +88,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// the same name and simplifies subsequent handling.
|
||||
// See [rustc-dev-guide chapter] § "Semantic lifetime equality".
|
||||
NllRegionVariableOrigin::FreeRegion => self
|
||||
.universal_regions
|
||||
.universal_regions()
|
||||
.universal_regions_iter()
|
||||
.filter(|&ur| {
|
||||
// See [rustc-dev-guide chapter] § "Closure restrictions".
|
||||
!matches!(
|
||||
self.universal_regions.region_classification(ur),
|
||||
self.universal_regions().region_classification(ur),
|
||||
Some(RegionClassification::External)
|
||||
)
|
||||
})
|
||||
|
@ -45,8 +45,8 @@ impl RegionInferenceContext<'_> {
|
||||
|
||||
let graph = self.constraint_sccs.reverse();
|
||||
let mut paired_scc_regions = self
|
||||
.universal_regions
|
||||
.universal_regions()
|
||||
.universal_regions_iter()
|
||||
.map(|region| (self.constraint_sccs.scc(region), region))
|
||||
.collect::<Vec<_>>();
|
||||
paired_scc_regions.sort();
|
||||
|
@ -258,10 +258,9 @@ impl PlaceholderIndices {
|
||||
/// Here, the variable `'0` would contain the free region `'a`,
|
||||
/// because (since it is returned) it must live for at least `'a`. But
|
||||
/// it would also contain various points from within the function.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct RegionValues<N: Idx> {
|
||||
elements: Rc<DenseLocationMap>,
|
||||
placeholder_indices: Rc<PlaceholderIndices>,
|
||||
placeholder_indices: PlaceholderIndices,
|
||||
points: SparseIntervalMatrix<N, PointIndex>,
|
||||
free_regions: SparseBitMatrix<N, RegionVid>,
|
||||
|
||||
@ -277,7 +276,7 @@ impl<N: Idx> RegionValues<N> {
|
||||
pub(crate) fn new(
|
||||
elements: Rc<DenseLocationMap>,
|
||||
num_universal_regions: usize,
|
||||
placeholder_indices: Rc<PlaceholderIndices>,
|
||||
placeholder_indices: PlaceholderIndices,
|
||||
) -> Self {
|
||||
let num_points = elements.num_points();
|
||||
let num_placeholders = placeholder_indices.len();
|
||||
|
@ -132,7 +132,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
let param_env = self.param_env;
|
||||
let param_env = self.infcx.param_env;
|
||||
let predicate = predicate.upcast(self.tcx());
|
||||
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
|
||||
locations,
|
||||
@ -158,7 +158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
where
|
||||
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
|
||||
{
|
||||
let param_env = self.param_env;
|
||||
let param_env = self.infcx.param_env;
|
||||
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
|
||||
location.to_locations(),
|
||||
category,
|
||||
@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let tcx = self.tcx();
|
||||
if self.infcx.next_trait_solver() {
|
||||
let body = self.body;
|
||||
let param_env = self.param_env;
|
||||
let param_env = self.infcx.param_env;
|
||||
self.fully_perform_op(
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
@ -223,7 +223,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::Boring,
|
||||
self.param_env.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
|
||||
self.infcx
|
||||
.param_env
|
||||
.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
|
||||
);
|
||||
}
|
||||
|
||||
@ -250,7 +252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let mir_ty = self.normalize(mir_ty, Locations::All(span));
|
||||
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
let param_env = self.param_env;
|
||||
let param_env = self.infcx.param_env;
|
||||
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::Boring,
|
||||
|
@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
@ -52,7 +52,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
|
||||
use rustc_hir::def::DefKind;
|
||||
@ -23,7 +21,7 @@ use crate::universal_regions::UniversalRegions;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct UniversalRegionRelations<'tcx> {
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
pub(crate) universal_regions: UniversalRegions<'tcx>,
|
||||
|
||||
/// Stores the outlives relations that are known to hold from the
|
||||
/// implied bounds, in-scope where-clauses, and that sort of
|
||||
@ -46,7 +44,7 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
|
||||
pub(crate) struct CreateResult<'tcx> {
|
||||
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
pub(crate) known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
||||
}
|
||||
|
||||
@ -54,7 +52,7 @@ pub(crate) fn create<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||
) -> CreateResult<'tcx> {
|
||||
UniversalRegionRelationsBuilder {
|
||||
@ -184,7 +182,7 @@ impl UniversalRegionRelations<'_> {
|
||||
struct UniversalRegionRelationsBuilder<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||
|
||||
@ -220,7 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
// region `'r`, all of which are provided by our caller
|
||||
let fr_static = self.universal_regions.fr_static;
|
||||
let fr_fn_body = self.universal_regions.fr_fn_body;
|
||||
for fr in self.universal_regions.universal_regions() {
|
||||
for fr in self.universal_regions.universal_regions_iter() {
|
||||
debug!("build: relating free region {:?} to itself and to 'static", fr);
|
||||
self.relate_universal_regions(fr, fr);
|
||||
self.relate_universal_regions(fr_static, fr);
|
||||
@ -236,7 +234,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
// In the new solver, normalize the type-outlives obligation assumptions.
|
||||
if self.infcx.next_trait_solver() {
|
||||
match deeply_normalize(
|
||||
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
|
||||
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), param_env),
|
||||
outlives,
|
||||
) {
|
||||
Ok(normalized_outlives) => {
|
||||
@ -250,8 +248,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
|
||||
known_type_outlives_obligations.push(outlives);
|
||||
}
|
||||
let known_type_outlives_obligations =
|
||||
self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);
|
||||
|
||||
let unnormalized_input_output_tys = self
|
||||
.universal_regions
|
||||
@ -278,15 +274,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
if let Some(c) = constraints_unnorm {
|
||||
constraints.push(c)
|
||||
}
|
||||
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
|
||||
.param_env
|
||||
.and(type_op::normalize::Normalize { value: ty })
|
||||
.fully_perform(self.infcx, span)
|
||||
.unwrap_or_else(|guar| TypeOpOutput {
|
||||
output: Ty::new_error(self.infcx.tcx, guar),
|
||||
constraints: None,
|
||||
error_info: None,
|
||||
});
|
||||
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
|
||||
param_env
|
||||
.and(type_op::normalize::Normalize { value: ty })
|
||||
.fully_perform(self.infcx, span)
|
||||
.unwrap_or_else(|guar| TypeOpOutput {
|
||||
output: Ty::new_error(self.infcx.tcx, guar),
|
||||
constraints: None,
|
||||
error_info: None,
|
||||
});
|
||||
if let Some(c) = constraints_normalize {
|
||||
constraints.push(c)
|
||||
}
|
||||
@ -316,8 +312,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
// Add implied bounds from impl header.
|
||||
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
||||
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
||||
let result: Result<_, ErrorGuaranteed> = self
|
||||
.param_env
|
||||
let result: Result<_, ErrorGuaranteed> = param_env
|
||||
.and(type_op::normalize::Normalize { value: ty })
|
||||
.fully_perform(self.infcx, span);
|
||||
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
|
||||
@ -340,7 +335,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
&known_type_outlives_obligations,
|
||||
Locations::All(span),
|
||||
span,
|
||||
ConstraintCategory::Internal,
|
||||
|
@ -19,7 +19,7 @@ use tracing::{debug, instrument};
|
||||
|
||||
use super::{Locations, TypeChecker};
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::universal_regions::{DefiningTy, UniversalRegions};
|
||||
use crate::universal_regions::DefiningTy;
|
||||
|
||||
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
/// Check explicit closure signature annotation,
|
||||
@ -124,11 +124,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
#[instrument(skip(self, body, universal_regions), level = "debug")]
|
||||
#[instrument(skip(self, body), level = "debug")]
|
||||
pub(super) fn equate_inputs_and_outputs(
|
||||
&mut self,
|
||||
body: &Body<'tcx>,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
normalized_inputs_and_output: &[Ty<'tcx>],
|
||||
) {
|
||||
let (&normalized_output_ty, normalized_input_tys) =
|
||||
@ -161,7 +160,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
if let Some(mir_yield_ty) = body.yield_ty() {
|
||||
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||
self.equate_normalized_input_or_output(
|
||||
universal_regions.yield_ty.unwrap(),
|
||||
self.universal_regions.yield_ty.unwrap(),
|
||||
mir_yield_ty,
|
||||
yield_span,
|
||||
);
|
||||
@ -170,7 +169,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
if let Some(mir_resume_ty) = body.resume_ty() {
|
||||
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||
self.equate_normalized_input_or_output(
|
||||
universal_regions.resume_ty.unwrap(),
|
||||
self.universal_regions.resume_ty.unwrap(),
|
||||
mir_resume_ty,
|
||||
yield_span,
|
||||
);
|
||||
|
@ -32,14 +32,14 @@ pub(super) fn generate<'a, 'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &DenseLocationMap,
|
||||
flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
) {
|
||||
debug!("liveness::generate");
|
||||
|
||||
let free_regions = regions_that_outlive_free_regions(
|
||||
typeck.infcx.num_region_vars(),
|
||||
typeck.universal_regions,
|
||||
&typeck.universal_regions,
|
||||
&typeck.constraints.outlives_constraints,
|
||||
);
|
||||
let (relevant_live_locals, boring_locals) =
|
||||
@ -107,7 +107,7 @@ fn regions_that_outlive_free_regions<'tcx>(
|
||||
let rev_region_graph = rev_constraint_graph.region_graph(constraint_set, fr_static);
|
||||
|
||||
// Stack for the depth-first search. Start out with all the free regions.
|
||||
let mut stack: Vec<_> = universal_regions.universal_regions().collect();
|
||||
let mut stack: Vec<_> = universal_regions.universal_regions_iter().collect();
|
||||
|
||||
// Set of all free regions, plus anything that outlives them. Initially
|
||||
// just contains the free regions.
|
||||
|
@ -38,7 +38,7 @@ pub(super) fn trace<'a, 'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &DenseLocationMap,
|
||||
flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
relevant_live_locals: Vec<Local>,
|
||||
boring_locals: Vec<Local>,
|
||||
@ -113,7 +113,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
|
||||
|
||||
/// Results of dataflow tracking which variables (and paths) have been
|
||||
/// initialized.
|
||||
flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
|
||||
flow_inits: ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
|
||||
|
||||
/// Index indicating where each variable is assigned, used, or
|
||||
/// dropped.
|
||||
@ -608,7 +608,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
|
||||
value.visit_with(&mut for_liveness::FreeRegionsVisitor {
|
||||
tcx: typeck.tcx(),
|
||||
param_env: typeck.param_env,
|
||||
param_env: typeck.infcx.param_env,
|
||||
op: |r| {
|
||||
let live_region_vid = typeck.universal_regions.to_region_vid(r);
|
||||
|
||||
@ -621,6 +621,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
|
||||
|
||||
match typeck
|
||||
.infcx
|
||||
.param_env
|
||||
.and(DropckOutlives { dropped_ty })
|
||||
.fully_perform(typeck.infcx, DUMMY_SP)
|
||||
|
@ -118,17 +118,15 @@ mod relate_tys;
|
||||
/// - `elements` -- MIR region map
|
||||
pub(crate) fn type_check<'a, 'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
elements: Rc<DenseLocationMap>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
) -> MirTypeckResults<'tcx> {
|
||||
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
|
||||
let mut constraints = MirTypeckRegionConstraints {
|
||||
@ -148,9 +146,9 @@ pub(crate) fn type_check<'a, 'tcx>(
|
||||
known_type_outlives_obligations,
|
||||
} = free_region_relations::create(
|
||||
infcx,
|
||||
param_env,
|
||||
infcx.param_env,
|
||||
implicit_region_bound,
|
||||
Rc::clone(&universal_regions),
|
||||
universal_regions,
|
||||
&mut constraints,
|
||||
);
|
||||
|
||||
@ -158,29 +156,27 @@ pub(crate) fn type_check<'a, 'tcx>(
|
||||
|
||||
let mut checker = TypeChecker {
|
||||
infcx,
|
||||
param_env,
|
||||
last_span: body.span,
|
||||
body,
|
||||
user_type_annotations: &body.user_type_annotations,
|
||||
region_bound_pairs: ®ion_bound_pairs,
|
||||
region_bound_pairs,
|
||||
known_type_outlives_obligations,
|
||||
implicit_region_bound,
|
||||
reported_errors: Default::default(),
|
||||
universal_regions: &universal_regions,
|
||||
universal_regions: &universal_region_relations.universal_regions,
|
||||
location_table,
|
||||
all_facts,
|
||||
borrow_set,
|
||||
constraints: &mut constraints,
|
||||
upvars,
|
||||
};
|
||||
|
||||
checker.check_user_type_annotations();
|
||||
|
||||
let mut verifier = TypeVerifier::new(&mut checker, promoted);
|
||||
let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span };
|
||||
verifier.visit_body(body);
|
||||
|
||||
checker.typeck_mir(body);
|
||||
checker.equate_inputs_and_outputs(body, &universal_regions, &normalized_inputs_and_output);
|
||||
checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
|
||||
checker.check_signature_annotation(body);
|
||||
|
||||
liveness::generate(&mut checker, body, &elements, flow_inits, move_data);
|
||||
@ -467,13 +463,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
fn new(
|
||||
cx: &'a mut TypeChecker<'b, 'tcx>,
|
||||
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
|
||||
) -> Self {
|
||||
TypeVerifier { promoted, last_span: cx.body.span, cx }
|
||||
}
|
||||
|
||||
fn body(&self) -> &Body<'tcx> {
|
||||
self.cx.body
|
||||
}
|
||||
@ -837,14 +826,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
/// NLL region checking.
|
||||
struct TypeChecker<'a, 'tcx> {
|
||||
infcx: &'a BorrowckInferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
last_span: Span,
|
||||
body: &'a Body<'tcx>,
|
||||
/// User type annotations are shared between the main MIR and the MIR of
|
||||
/// all of the promoted items.
|
||||
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
|
||||
universal_regions: &'a UniversalRegions<'tcx>,
|
||||
@ -852,7 +840,6 @@ struct TypeChecker<'a, 'tcx> {
|
||||
all_facts: &'a mut Option<AllFacts>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||
upvars: &'a [&'a ty::CapturedPlace<'tcx>],
|
||||
}
|
||||
|
||||
/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
|
||||
@ -1025,10 +1012,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
self.infcx.param_env,
|
||||
&self.known_type_outlives_obligations,
|
||||
locations,
|
||||
locations.span(self.body),
|
||||
category,
|
||||
@ -1527,9 +1514,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// The signature in this call can reference region variables,
|
||||
// so erase them before calling a query.
|
||||
let output_ty = self.tcx().erase_regions(sig.output());
|
||||
if !output_ty
|
||||
.is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.param_env))
|
||||
{
|
||||
if !output_ty.is_privately_uninhabited(
|
||||
self.tcx(),
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
) {
|
||||
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
|
||||
}
|
||||
}
|
||||
@ -1739,7 +1727,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// `Sized` bound in no way depends on precise regions, so this
|
||||
// shouldn't affect `is_sized`.
|
||||
let erased_ty = tcx.erase_regions(ty);
|
||||
if !erased_ty.is_sized(tcx, self.param_env) {
|
||||
if !erased_ty.is_sized(tcx, self.infcx.param_env) {
|
||||
// in current MIR construction, all non-control-flow rvalue
|
||||
// expressions evaluate through `as_temp` or `into` a return
|
||||
// slot or local, so to find all unsized rvalues it is enough
|
||||
@ -2631,8 +2619,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let def = self.body.source.def_id().expect_local();
|
||||
let upvars = tcx.closure_captures(def);
|
||||
let field =
|
||||
path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body);
|
||||
path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body);
|
||||
let category = if let Some(field) = field {
|
||||
ConstraintCategory::ClosureUpvar(field)
|
||||
} else {
|
||||
@ -2787,10 +2777,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
self.infcx.param_env,
|
||||
&self.known_type_outlives_obligations,
|
||||
locations,
|
||||
self.body.span, // irrelevant; will be overridden.
|
||||
ConstraintCategory::Boring, // same as above.
|
||||
|
@ -522,7 +522,7 @@ impl<'b, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.type_checker.param_env
|
||||
self.type_checker.infcx.param_env
|
||||
}
|
||||
|
||||
fn register_predicates(
|
||||
|
@ -248,12 +248,8 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
/// MIR -- that is, all the regions that appear in the function's
|
||||
/// signature. This will also compute the relationships that are
|
||||
/// known between those regions.
|
||||
pub(crate) fn new(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
mir_def: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Self {
|
||||
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
|
||||
pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
|
||||
UniversalRegionsBuilder { infcx, mir_def }.build()
|
||||
}
|
||||
|
||||
/// Given a reference to a closure type, extracts all the values
|
||||
@ -312,7 +308,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
|
||||
/// Returns an iterator over all the RegionVids corresponding to
|
||||
/// universally quantified free regions.
|
||||
pub(crate) fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
|
||||
pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> {
|
||||
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
|
||||
}
|
||||
|
||||
@ -336,7 +332,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
}
|
||||
|
||||
/// Gets an iterator over all the early-bound regions that have names.
|
||||
pub(crate) fn named_universal_regions<'s>(
|
||||
pub(crate) fn named_universal_regions_iter<'s>(
|
||||
&'s self,
|
||||
) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
|
||||
self.indices.indices.iter().map(|(&r, &v)| (r, v))
|
||||
@ -426,7 +422,6 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
struct UniversalRegionsBuilder<'infcx, 'tcx> {
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
mir_def: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
const FR: NllRegionVariableOrigin = NllRegionVariableOrigin::FreeRegion;
|
||||
@ -435,7 +430,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
fn build(self) -> UniversalRegions<'tcx> {
|
||||
debug!("build(mir_def={:?})", self.mir_def);
|
||||
|
||||
let param_env = self.param_env;
|
||||
let param_env = self.infcx.param_env;
|
||||
debug!("build: param_env={:?}", param_env);
|
||||
|
||||
assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
|
||||
|
@ -21,6 +21,7 @@
|
||||
#![feature(auto_traits)]
|
||||
#![feature(cfg_match)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(hash_raw_entry)]
|
||||
@ -78,6 +79,7 @@ pub mod thinvec;
|
||||
pub mod transitive_relation;
|
||||
pub mod unhash;
|
||||
pub mod unord;
|
||||
pub mod vec_cache;
|
||||
pub mod work_queue;
|
||||
|
||||
mod atomic_ref;
|
||||
|
324
compiler/rustc_data_structures/src/vec_cache.rs
Normal file
324
compiler/rustc_data_structures/src/vec_cache.rs
Normal file
@ -0,0 +1,324 @@
|
||||
//! VecCache maintains a mapping from K -> (V, I) pairing. K and I must be roughly u32-sized, and V
|
||||
//! must be Copy.
|
||||
//!
|
||||
//! VecCache supports efficient concurrent put/get across the key space, with write-once semantics
|
||||
//! (i.e., a given key can only be put once). Subsequent puts will panic.
|
||||
//!
|
||||
//! This is currently used for query caching.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicUsize, Ordering};
|
||||
|
||||
use rustc_index::Idx;
|
||||
|
||||
struct Slot<V> {
|
||||
// We never construct &Slot<V> so it's fine for this to not be in an UnsafeCell.
|
||||
value: V,
|
||||
// This is both an index and a once-lock.
|
||||
//
|
||||
// 0: not yet initialized.
|
||||
// 1: lock held, initializing.
|
||||
// 2..u32::MAX - 2: initialized.
|
||||
index_and_lock: AtomicU32,
|
||||
}
|
||||
|
||||
/// This uniquely identifies a single `Slot<V>` entry in the buckets map, and provides accessors for
|
||||
/// either getting the value or putting a value.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct SlotIndex {
|
||||
// the index of the bucket in VecCache (0 to 20)
|
||||
bucket_idx: usize,
|
||||
// number of entries in that bucket
|
||||
entries: usize,
|
||||
// the index of the slot within the bucket
|
||||
index_in_bucket: usize,
|
||||
}
|
||||
|
||||
// This makes sure the counts are consistent with what we allocate, precomputing each bucket a
|
||||
// compile-time. Visiting all powers of two is enough to hit all the buckets.
|
||||
//
|
||||
// We confirm counts are accurate in the slot_index_exhaustive test.
|
||||
const ENTRIES_BY_BUCKET: [usize; 21] = {
|
||||
let mut entries = [0; 21];
|
||||
let mut key = 0;
|
||||
loop {
|
||||
let si = SlotIndex::from_index(key);
|
||||
entries[si.bucket_idx] = si.entries;
|
||||
if key == 0 {
|
||||
key = 1;
|
||||
} else if key == (1 << 31) {
|
||||
break;
|
||||
} else {
|
||||
key <<= 1;
|
||||
}
|
||||
}
|
||||
entries
|
||||
};
|
||||
|
||||
impl SlotIndex {
|
||||
// This unpacks a flat u32 index into identifying which bucket it belongs to and the offset
|
||||
// within that bucket. As noted in the VecCache docs, buckets double in size with each index.
|
||||
// Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce
|
||||
// the size of the VecCache struct and avoid uselessly small allocations, we instead have the
|
||||
// first bucket have 2**12 entries. To simplify the math, the second bucket also 2**12 entries,
|
||||
// and buckets double from there.
|
||||
//
|
||||
// We assert that [0, 2**32 - 1] uniquely map through this function to individual, consecutive
|
||||
// slots (see `slot_index_exhaustive` in tests).
|
||||
#[inline]
|
||||
const fn from_index(idx: u32) -> Self {
|
||||
let mut bucket = match idx.checked_ilog2() {
|
||||
Some(x) => x as usize,
|
||||
None => 0,
|
||||
};
|
||||
let entries;
|
||||
let running_sum;
|
||||
if bucket <= 11 {
|
||||
entries = 1 << 12;
|
||||
running_sum = 0;
|
||||
bucket = 0;
|
||||
} else {
|
||||
entries = 1 << bucket;
|
||||
running_sum = entries;
|
||||
bucket = bucket - 11;
|
||||
}
|
||||
SlotIndex { bucket_idx: bucket, entries, index_in_bucket: idx as usize - running_sum }
|
||||
}
|
||||
|
||||
// SAFETY: Buckets must be managed solely by functions here (i.e., get/put on SlotIndex) and
|
||||
// `self` comes from SlotIndex::from_index
|
||||
#[inline]
|
||||
unsafe fn get<V: Copy>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) -> Option<(V, u32)> {
|
||||
// SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
|
||||
// in-bounds of buckets. See `from_index` for computation.
|
||||
let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
|
||||
let ptr = bucket.load(Ordering::Acquire);
|
||||
// Bucket is not yet initialized: then we obviously won't find this entry in that bucket.
|
||||
if ptr.is_null() {
|
||||
return None;
|
||||
}
|
||||
assert!(self.index_in_bucket < self.entries);
|
||||
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
|
||||
// must be inbounds.
|
||||
let slot = unsafe { ptr.add(self.index_in_bucket) };
|
||||
|
||||
// SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
|
||||
// AtomicU32 access.
|
||||
let index_and_lock = unsafe { &(*slot).index_and_lock };
|
||||
let current = index_and_lock.load(Ordering::Acquire);
|
||||
let index = match current {
|
||||
0 => return None,
|
||||
// Treat "initializing" as actually just not initialized at all.
|
||||
// The only reason this is a separate state is that `complete` calls could race and
|
||||
// we can't allow that, but from load perspective there's no difference.
|
||||
1 => return None,
|
||||
_ => current - 2,
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// * slot is a valid pointer (buckets are always valid for the index we get).
|
||||
// * value is initialized since we saw a >= 2 index above.
|
||||
// * `V: Copy`, so safe to read.
|
||||
let value = unsafe { (*slot).value };
|
||||
Some((value, index))
|
||||
}
|
||||
|
||||
fn bucket_ptr<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
|
||||
let ptr = bucket.load(Ordering::Acquire);
|
||||
if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr }
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn initialize_bucket<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
|
||||
static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
|
||||
// If we are initializing the bucket, then acquire a global lock.
|
||||
//
|
||||
// This path is quite cold, so it's cheap to use a global lock. This ensures that we never
|
||||
// have multiple allocations for the same bucket.
|
||||
let _allocator_guard = LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||
|
||||
let ptr = bucket.load(Ordering::Acquire);
|
||||
|
||||
// OK, now under the allocator lock, if we're still null then it's definitely us that will
|
||||
// initialize this bucket.
|
||||
if ptr.is_null() {
|
||||
let bucket_layout =
|
||||
std::alloc::Layout::array::<Slot<V>>(self.entries as usize).unwrap();
|
||||
// This is more of a sanity check -- this code is very cold, so it's safe to pay a
|
||||
// little extra cost here.
|
||||
assert!(bucket_layout.size() > 0);
|
||||
// SAFETY: Just checked that size is non-zero.
|
||||
let allocated = unsafe { std::alloc::alloc_zeroed(bucket_layout).cast::<Slot<V>>() };
|
||||
if allocated.is_null() {
|
||||
std::alloc::handle_alloc_error(bucket_layout);
|
||||
}
|
||||
bucket.store(allocated, Ordering::Release);
|
||||
allocated
|
||||
} else {
|
||||
// Otherwise some other thread initialized this bucket after we took the lock. In that
|
||||
// case, just return early.
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this successfully put into the map.
|
||||
#[inline]
|
||||
fn put<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) -> bool {
|
||||
// SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
|
||||
// in-bounds of buckets.
|
||||
let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
|
||||
let ptr = self.bucket_ptr(bucket);
|
||||
|
||||
assert!(self.index_in_bucket < self.entries);
|
||||
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
|
||||
// must be inbounds.
|
||||
let slot = unsafe { ptr.add(self.index_in_bucket) };
|
||||
|
||||
// SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
|
||||
// AtomicU32 access.
|
||||
let index_and_lock = unsafe { &(*slot).index_and_lock };
|
||||
match index_and_lock.compare_exchange(0, 1, Ordering::AcqRel, Ordering::Acquire) {
|
||||
Ok(_) => {
|
||||
// We have acquired the initialization lock. It is our job to write `value` and
|
||||
// then set the lock to the real index.
|
||||
|
||||
unsafe {
|
||||
(&raw mut (*slot).value).write(value);
|
||||
}
|
||||
|
||||
index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
// Treat "initializing" as the caller's fault. Callers are responsible for ensuring that
|
||||
// there are no races on initialization. In the compiler's current usage for query
|
||||
// caches, that's the "active query map" which ensures each query actually runs once
|
||||
// (even if concurrently started).
|
||||
Err(1) => panic!("caller raced calls to put()"),
|
||||
|
||||
// This slot was already populated. Also ignore, currently this is the same as
|
||||
// "initializing".
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecCache<K: Idx, V, I> {
|
||||
// Entries per bucket:
|
||||
// Bucket 0: 4096 2^12
|
||||
// Bucket 1: 4096 2^12
|
||||
// Bucket 2: 8192
|
||||
// Bucket 3: 16384
|
||||
// ...
|
||||
// Bucket 19: 1073741824
|
||||
// Bucket 20: 2147483648
|
||||
// The total number of entries if all buckets are initialized is u32::MAX-1.
|
||||
buckets: [AtomicPtr<Slot<V>>; 21],
|
||||
|
||||
// In the compiler's current usage these are only *read* during incremental and self-profiling.
|
||||
// They are an optimization over iterating the full buckets array.
|
||||
present: [AtomicPtr<Slot<()>>; 21],
|
||||
len: AtomicUsize,
|
||||
|
||||
key: PhantomData<(K, I)>,
|
||||
}
|
||||
|
||||
impl<K: Idx, V, I> Default for VecCache<K, V, I> {
|
||||
fn default() -> Self {
|
||||
VecCache {
|
||||
buckets: Default::default(),
|
||||
key: PhantomData,
|
||||
len: Default::default(),
|
||||
present: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: No access to `V` is made.
|
||||
unsafe impl<K: Idx, #[may_dangle] V, I> Drop for VecCache<K, V, I> {
|
||||
fn drop(&mut self) {
|
||||
// We have unique ownership, so no locks etc. are needed. Since `K` and `V` are both `Copy`,
|
||||
// we are also guaranteed to just need to deallocate any large arrays (not iterate over
|
||||
// contents).
|
||||
//
|
||||
// Confirm no need to deallocate invidual entries. Note that `V: Copy` is asserted on
|
||||
// insert/lookup but not necessarily construction, primarily to avoid annoyingly propagating
|
||||
// the bounds into struct definitions everywhere.
|
||||
assert!(!std::mem::needs_drop::<K>());
|
||||
assert!(!std::mem::needs_drop::<V>());
|
||||
|
||||
for (idx, bucket) in self.buckets.iter().enumerate() {
|
||||
let bucket = bucket.load(Ordering::Acquire);
|
||||
if !bucket.is_null() {
|
||||
let layout = std::alloc::Layout::array::<Slot<V>>(ENTRIES_BY_BUCKET[idx]).unwrap();
|
||||
unsafe {
|
||||
std::alloc::dealloc(bucket.cast(), layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, bucket) in self.present.iter().enumerate() {
|
||||
let bucket = bucket.load(Ordering::Acquire);
|
||||
if !bucket.is_null() {
|
||||
let layout = std::alloc::Layout::array::<Slot<()>>(ENTRIES_BY_BUCKET[idx]).unwrap();
|
||||
unsafe {
|
||||
std::alloc::dealloc(bucket.cast(), layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, I> VecCache<K, V, I>
|
||||
where
|
||||
K: Eq + Idx + Copy + Debug,
|
||||
V: Copy,
|
||||
I: Idx + Copy,
|
||||
{
|
||||
#[inline(always)]
|
||||
pub fn lookup(&self, key: &K) -> Option<(V, I)> {
|
||||
let key = u32::try_from(key.index()).unwrap();
|
||||
let slot_idx = SlotIndex::from_index(key);
|
||||
match unsafe { slot_idx.get(&self.buckets) } {
|
||||
Some((value, idx)) => Some((value, I::new(idx as usize))),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn complete(&self, key: K, value: V, index: I) {
|
||||
let key = u32::try_from(key.index()).unwrap();
|
||||
let slot_idx = SlotIndex::from_index(key);
|
||||
if slot_idx.put(&self.buckets, value, index.index() as u32) {
|
||||
let present_idx = self.len.fetch_add(1, Ordering::Relaxed);
|
||||
let slot = SlotIndex::from_index(present_idx as u32);
|
||||
// We should always be uniquely putting due to `len` fetch_add returning unique values.
|
||||
assert!(slot.put(&self.present, (), key));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self, f: &mut dyn FnMut(&K, &V, I)) {
|
||||
for idx in 0..self.len.load(Ordering::Acquire) {
|
||||
let key = SlotIndex::from_index(idx as u32);
|
||||
match unsafe { key.get(&self.present) } {
|
||||
// This shouldn't happen in our current usage (iter is really only
|
||||
// used long after queries are done running), but if we hit this in practice it's
|
||||
// probably fine to just break early.
|
||||
None => unreachable!(),
|
||||
Some(((), key)) => {
|
||||
let key = K::new(key as usize);
|
||||
// unwrap() is OK: present entries are always written only after we put the real
|
||||
// entry.
|
||||
let value = self.lookup(&key).unwrap();
|
||||
f(&key, &value.0, value.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
95
compiler/rustc_data_structures/src/vec_cache/tests.rs
Normal file
95
compiler/rustc_data_structures/src/vec_cache/tests.rs
Normal file
@ -0,0 +1,95 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
fn vec_cache_empty() {
|
||||
let cache: VecCache<u32, u32, u32> = VecCache::default();
|
||||
for key in 0..u32::MAX {
|
||||
assert!(cache.lookup(&key).is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_cache_insert_and_check() {
|
||||
let cache: VecCache<u32, u32, u32> = VecCache::default();
|
||||
cache.complete(0, 1, 2);
|
||||
assert_eq!(cache.lookup(&0), Some((1, 2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sparse_inserts() {
|
||||
let cache: VecCache<u32, u8, u32> = VecCache::default();
|
||||
let end = if cfg!(target_pointer_width = "64") && cfg!(target_os = "linux") {
|
||||
// For paged memory, 64-bit systems we should be able to sparsely allocate all of the pages
|
||||
// needed for these inserts cheaply (without needing to actually have gigabytes of resident
|
||||
// memory).
|
||||
31
|
||||
} else {
|
||||
// Otherwise, still run the test but scaled back:
|
||||
//
|
||||
// Each slot is 5 bytes, so 2^25 entries (on non-virtual memory systems, like e.g. Windows) will
|
||||
// mean 160 megabytes of allocated memory. Going beyond that is probably not reasonable for
|
||||
// tests.
|
||||
25
|
||||
};
|
||||
for shift in 0..end {
|
||||
let key = 1u32 << shift;
|
||||
cache.complete(key, shift, key);
|
||||
assert_eq!(cache.lookup(&key), Some((shift, key)));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concurrent_stress_check() {
|
||||
let cache: VecCache<u32, u32, u32> = VecCache::default();
|
||||
std::thread::scope(|s| {
|
||||
for idx in 0..100 {
|
||||
let cache = &cache;
|
||||
s.spawn(move || {
|
||||
cache.complete(idx, idx, idx);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for idx in 0..100 {
|
||||
assert_eq!(cache.lookup(&idx), Some((idx, idx)));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slot_entries_table() {
|
||||
assert_eq!(ENTRIES_BY_BUCKET, [
|
||||
4096, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
|
||||
8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
|
||||
2147483648
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
fn slot_index_exhaustive() {
|
||||
let mut buckets = [0u32; 21];
|
||||
for idx in 0..=u32::MAX {
|
||||
buckets[SlotIndex::from_index(idx).bucket_idx] += 1;
|
||||
}
|
||||
let mut prev = None::<SlotIndex>;
|
||||
for idx in 0..=u32::MAX {
|
||||
let slot_idx = SlotIndex::from_index(idx);
|
||||
if let Some(p) = prev {
|
||||
if p.bucket_idx == slot_idx.bucket_idx {
|
||||
assert_eq!(p.index_in_bucket + 1, slot_idx.index_in_bucket);
|
||||
} else {
|
||||
assert_eq!(slot_idx.index_in_bucket, 0);
|
||||
}
|
||||
} else {
|
||||
assert_eq!(idx, 0);
|
||||
assert_eq!(slot_idx.index_in_bucket, 0);
|
||||
assert_eq!(slot_idx.bucket_idx, 0);
|
||||
}
|
||||
|
||||
assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32);
|
||||
assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx);
|
||||
|
||||
prev = Some(slot_idx);
|
||||
}
|
||||
}
|
@ -529,6 +529,8 @@ declare_features! (
|
||||
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
||||
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
||||
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
||||
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
|
||||
(incomplete, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980)),
|
||||
/// A minimal, sound subset of specialization intended to be used by the
|
||||
/// standard library until the soundness issues with specialization
|
||||
/// are fixed.
|
||||
|
@ -46,7 +46,7 @@ use tracing::{debug, instrument};
|
||||
|
||||
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
|
||||
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
|
||||
|
||||
pub(crate) mod dump;
|
||||
mod generics_of;
|
||||
@ -88,6 +88,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
coroutine_for_closure,
|
||||
opaque_ty_origin,
|
||||
rendered_precise_capturing_args,
|
||||
const_param_default,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
@ -1790,3 +1791,23 @@ fn rendered_precise_capturing_args<'tcx>(
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn const_param_default<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) => ct,
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
// FIXME(const_generics): investigate which places do and don't need const ty feeding
|
||||
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
|
||||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
|
@ -223,11 +223,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
trace!(?predicates);
|
||||
}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
let param_def_id = param.def_id.to_def_id();
|
||||
let ct_ty = tcx
|
||||
.type_of(param.def_id.to_def_id())
|
||||
.type_of(param_def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameters cannot be generic");
|
||||
let ct = icx.lowerer().lower_const_param(param.hir_id);
|
||||
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
|
||||
predicates
|
||||
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ use tracing::{debug, instrument};
|
||||
use super::errors::GenericsArgsErrExtend;
|
||||
use crate::bounds::Bounds;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
|
||||
use crate::hir_ty_lowering::{
|
||||
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
|
||||
};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Add a `Sized` bound to the `bounds` if appropriate.
|
||||
@ -346,9 +348,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
hir::AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => {
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
|
||||
}
|
||||
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
|
||||
};
|
||||
|
||||
// Find any late-bound regions declared in `ty` that are not
|
||||
|
@ -115,17 +115,22 @@ fn generic_arg_mismatch_err(
|
||||
}
|
||||
}
|
||||
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
||||
// FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
|
||||
// this should match against that instead of ::Anon
|
||||
if let hir::ConstArgKind::Anon(anon) = cnst.kind
|
||||
if let hir::ConstArgKind::Path(qpath) = cnst.kind
|
||||
&& let rustc_hir::QPath::Resolved(_, path) = qpath
|
||||
&& let Res::Def(DefKind::Fn { .. }, id) = path.res
|
||||
{
|
||||
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||
err.help("function item types cannot be named directly");
|
||||
} else if let hir::ConstArgKind::Anon(anon) = cnst.kind
|
||||
&& let body = tcx.hir().body(anon.body)
|
||||
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
|
||||
body.value.kind
|
||||
&& let Res::Def(DefKind::Fn { .. }, id) = path.res
|
||||
{
|
||||
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
|
||||
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||
err.help("function item types cannot be named directly");
|
||||
}
|
||||
// FIXME(min_generic_const_args): this branch is dead once new const path lowering
|
||||
// (for single-segment paths) is no longer gated
|
||||
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||
err.help("function item types cannot be named directly");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{GenericArg, GenericArgs, HirId};
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
@ -217,6 +217,23 @@ impl AssocItemQSelf {
|
||||
}
|
||||
}
|
||||
|
||||
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||
/// through const generics need to have their type "fed" to them
|
||||
/// using the query system.
|
||||
///
|
||||
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
|
||||
/// desired behavior.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FeedConstTy {
|
||||
/// Feed the type.
|
||||
///
|
||||
/// The `DefId` belongs to the const param that we are supplying
|
||||
/// this (anon) const arg to.
|
||||
Param(DefId),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
}
|
||||
|
||||
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
||||
/// are present in a set of generic arguments.
|
||||
///
|
||||
@ -500,8 +517,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
handle_ty_args(has_default, &inf.to_ty())
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
|
||||
.into()
|
||||
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
|
||||
}
|
||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||
@ -979,8 +995,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let term: ty::Term<'_> = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => {
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
|
||||
.into()
|
||||
self.lower_const_arg(ct, FeedConstTy::No).into()
|
||||
}
|
||||
};
|
||||
// FIXME(#97583): This isn't syntactically well-formed!
|
||||
@ -2025,23 +2040,138 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
///
|
||||
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
|
||||
/// and late-bound ones to [`ty::ConstKind::Bound`].
|
||||
pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> {
|
||||
pub(crate) fn lower_const_param(&self, param_def_id: DefId, path_hir_id: HirId) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
match tcx.named_bound_var(hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
||||
|
||||
match tcx.named_bound_var(path_hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||
// Find the name and index of the const parameter by indexing the generics of
|
||||
// the parent item and construct a `ParamConst`.
|
||||
let item_def_id = tcx.local_parent(def_id);
|
||||
let item_def_id = tcx.parent(param_def_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
|
||||
let name = tcx.item_name(def_id.to_def_id());
|
||||
let index = generics.param_def_id_to_index[¶m_def_id];
|
||||
let name = tcx.item_name(param_def_id);
|
||||
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||
}
|
||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn lower_const_arg(
|
||||
&self,
|
||||
const_arg: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let FeedConstTy::Param(param_def_id) = feed
|
||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||
{
|
||||
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||
}
|
||||
|
||||
let hir_id = const_arg.hir_id;
|
||||
match const_arg.kind {
|
||||
hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
|
||||
debug!(?maybe_qself, ?path);
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
||||
self.lower_const_path_resolved(opt_self_ty, path, hir_id)
|
||||
}
|
||||
hir::ConstArgKind::Path(qpath) => ty::Const::new_error_with_message(
|
||||
tcx,
|
||||
qpath.span(),
|
||||
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
|
||||
),
|
||||
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_const_path_resolved(
|
||||
&self,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
path: &hir::Path<'tcx>,
|
||||
hir_id: HirId,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let span = path.span;
|
||||
match path.res {
|
||||
Res::Def(DefKind::ConstParam, def_id) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.iter(),
|
||||
GenericsArgsErrExtend::Param(def_id),
|
||||
);
|
||||
self.lower_const_param(def_id, hir_id)
|
||||
}
|
||||
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let args = self.lower_generic_args_of_path_segment(
|
||||
span,
|
||||
did,
|
||||
path.segments.last().unwrap(),
|
||||
);
|
||||
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||
}
|
||||
Res::Def(DefKind::Static { .. }, _) => {
|
||||
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
|
||||
}
|
||||
// FIXME(const_generics): create real const to allow fn items as const paths
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
"fn items cannot be used as const args",
|
||||
),
|
||||
|
||||
// Exhaustive match to be clear about what exactly we're considering to be
|
||||
// an invalid Res for a const path.
|
||||
Res::Def(
|
||||
DefKind::Mod
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
|
||||
| DefKind::Struct
|
||||
| DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::Union
|
||||
| DefKind::Trait
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::AssocConst
|
||||
| DefKind::TyParam
|
||||
| DefKind::Macro(_)
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::AnonConst
|
||||
| DefKind::InlineConst
|
||||
| DefKind::Field
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::Closure
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::SyntheticCoroutineBody,
|
||||
_,
|
||||
)
|
||||
| Res::PrimTy(_)
|
||||
| Res::SelfTyParam { .. }
|
||||
| Res::SelfTyAlias { .. }
|
||||
| Res::SelfCtor(_)
|
||||
| Res::Local(_)
|
||||
| Res::ToolMod
|
||||
| Res::NonMacroAttr(_)
|
||||
| Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2053,14 +2183,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower a type from the HIR to our internal notion of a type given some extra data for diagnostics.
|
||||
///
|
||||
/// Extra diagnostic data:
|
||||
///
|
||||
/// 1. `borrowed`: Whether trait object types are borrowed like in `&dyn Trait`.
|
||||
/// Used to avoid emitting redundant errors.
|
||||
/// 2. `in_path`: Whether the type appears inside of a path.
|
||||
/// Used to provide correct diagnostics for bare trait object types.
|
||||
/// Lower a type from the HIR to our internal notion of a type.
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
@ -2189,7 +2312,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let length = match length {
|
||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||
hir::ArrayLen::Body(constant) => {
|
||||
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
|
||||
self.lower_const_arg(constant, FeedConstTy::No)
|
||||
}
|
||||
};
|
||||
|
||||
@ -2247,7 +2370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
.type_of(def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic");
|
||||
let ct = self.lower_const_param(expr.hir_id);
|
||||
let ct = self.lower_const_param(def_id, expr.hir_id);
|
||||
(ct, ty)
|
||||
}
|
||||
|
||||
|
@ -97,12 +97,14 @@ use rustc_hir::def::DefKind;
|
||||
use rustc_middle::middle;
|
||||
use rustc_middle::mir::interpret::GlobalId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
fn require_c_abi_if_c_variadic(
|
||||
@ -226,3 +228,14 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
|
||||
}
|
||||
|
||||
/// This is for rustdoc.
|
||||
// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
|
||||
pub fn lower_const_arg_for_rustdoc<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_ct: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
) -> Const<'tcx> {
|
||||
let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
|
||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
|
||||
check_generic_arg_count_for_call, lower_generic_args,
|
||||
};
|
||||
use rustc_hir_analysis::hir_ty_lowering::{
|
||||
ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
|
||||
GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
|
||||
ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult,
|
||||
GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
|
||||
};
|
||||
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
||||
@ -491,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||
hir::ArrayLen::Body(const_arg) => {
|
||||
let span = const_arg.span();
|
||||
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
|
||||
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
|
||||
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
||||
self.normalize(span, c)
|
||||
}
|
||||
@ -503,8 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||
param_def_id: DefId,
|
||||
) -> ty::Const<'tcx> {
|
||||
let ct =
|
||||
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
|
||||
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
|
||||
self.register_wf_obligation(
|
||||
ct.into(),
|
||||
self.tcx.hir().span(const_arg.hir_id),
|
||||
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use std::{env, fs, iter};
|
||||
|
||||
use rustc_ast::{self as ast, visit};
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
@ -24,7 +24,7 @@ use rustc_middle::util::Providers;
|
||||
use rustc_parse::{
|
||||
new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
|
||||
};
|
||||
use rustc_passes::{abi_test, hir_stats, layout_test};
|
||||
use rustc_passes::{abi_test, input_stats, layout_test};
|
||||
use rustc_resolve::Resolver;
|
||||
use rustc_session::code_stats::VTableSizeInfo;
|
||||
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
@ -54,28 +54,17 @@ pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
|
||||
})
|
||||
.map_err(|parse_error| parse_error.emit())?;
|
||||
|
||||
if sess.opts.unstable_opts.input_stats {
|
||||
eprintln!("Lines of code: {}", sess.source_map().count_lines());
|
||||
eprintln!("Pre-expansion node count: {}", count_nodes(&krate));
|
||||
}
|
||||
|
||||
if let Some(ref s) = sess.opts.unstable_opts.show_span {
|
||||
rustc_ast_passes::show_span::run(sess.dcx(), s, &krate);
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.hir_stats {
|
||||
hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
|
||||
if sess.opts.unstable_opts.input_stats {
|
||||
input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
|
||||
}
|
||||
|
||||
Ok(krate)
|
||||
}
|
||||
|
||||
fn count_nodes(krate: &ast::Crate) -> usize {
|
||||
let mut counter = rustc_ast_passes::node_count::NodeCounter::new();
|
||||
visit::walk_crate(&mut counter, krate);
|
||||
counter.count
|
||||
}
|
||||
|
||||
fn pre_expansion_lint<'a>(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
@ -290,11 +279,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
|
||||
let mut lint_buffer = resolver.lint_buffer.steal();
|
||||
|
||||
if sess.opts.unstable_opts.input_stats {
|
||||
eprintln!("Post-expansion node count: {}", count_nodes(krate));
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.hir_stats {
|
||||
hir_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
|
||||
input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
|
||||
}
|
||||
|
||||
// Needs to go *after* expansion to be able to check the results of macro expansion.
|
||||
@ -820,8 +805,8 @@ pub(crate) fn create_global_ctxt<'tcx>(
|
||||
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
|
||||
/// This function never fails.
|
||||
fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
if tcx.sess.opts.unstable_opts.hir_stats {
|
||||
rustc_passes::hir_stats::print_hir_stats(tcx);
|
||||
if tcx.sess.opts.unstable_opts.input_stats {
|
||||
rustc_passes::input_stats::print_hir_stats(tcx);
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
rustc_passes::hir_id_validator::check_crate(tcx);
|
||||
|
@ -698,7 +698,6 @@ fn test_unstable_options_tracking_hash() {
|
||||
untracked!(dylib_lto, true);
|
||||
untracked!(emit_stack_sizes, true);
|
||||
untracked!(future_incompat_test, true);
|
||||
untracked!(hir_stats, true);
|
||||
untracked!(identify_regions, true);
|
||||
untracked!(incremental_info, true);
|
||||
untracked!(incremental_verify_ich, true);
|
||||
|
@ -3185,6 +3185,7 @@ declare_lint! {
|
||||
pub UNEXPECTED_CFGS,
|
||||
Warn,
|
||||
"detects unexpected names and values in `#[cfg]` conditions",
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
|
||||
use rustc_hir::hir_id::{HirId, OwnerId};
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
@ -111,7 +112,7 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
|
||||
}
|
||||
|
||||
impl Key for CrateNum {
|
||||
type Cache<V> = VecCache<Self, V>;
|
||||
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
|
||||
|
||||
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
||||
DUMMY_SP
|
||||
@ -128,7 +129,7 @@ impl AsLocalKey for CrateNum {
|
||||
}
|
||||
|
||||
impl Key for OwnerId {
|
||||
type Cache<V> = VecCache<Self, V>;
|
||||
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
self.to_def_id().default_span(tcx)
|
||||
@ -140,7 +141,7 @@ impl Key for OwnerId {
|
||||
}
|
||||
|
||||
impl Key for LocalDefId {
|
||||
type Cache<V> = VecCache<Self, V>;
|
||||
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
self.to_def_id().default_span(tcx)
|
||||
|
@ -1,13 +1,14 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::MultiSpan;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
use crate::mir::interpret::{LitToConstInput, Scalar};
|
||||
use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
|
||||
|
||||
@ -142,7 +143,7 @@ impl<'tcx> Const<'tcx> {
|
||||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: S,
|
||||
msg: &'static str,
|
||||
msg: impl Into<Cow<'static, str>>,
|
||||
) -> Const<'tcx> {
|
||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||
Const::new_error(tcx, reported)
|
||||
@ -183,46 +184,8 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||
/// through const generics need to have their type "fed" to them
|
||||
/// using the query system.
|
||||
///
|
||||
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
||||
/// desired behavior.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FeedConstTy {
|
||||
/// Feed the type.
|
||||
///
|
||||
/// The `DefId` belongs to the const param that we are supplying
|
||||
/// this (anon) const arg to.
|
||||
Param(DefId),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
}
|
||||
|
||||
impl<'tcx> Const<'tcx> {
|
||||
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn from_const_arg(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
) -> Self {
|
||||
if let FeedConstTy::Param(param_def_id) = feed
|
||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||
{
|
||||
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||
}
|
||||
|
||||
match const_arg.kind {
|
||||
hir::ConstArgKind::Path(qpath) => {
|
||||
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
|
||||
Self::from_param(tcx, qpath, const_arg.hir_id)
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
|
||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||
/// becomes `Unevaluated`.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
@ -240,7 +203,7 @@ impl<'tcx> Const<'tcx> {
|
||||
|
||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||
|
||||
match Self::try_from_lit_or_param(tcx, ty, expr) {
|
||||
match Self::try_from_lit(tcx, ty, expr) {
|
||||
Some(v) => v,
|
||||
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
||||
def: def.to_def_id(),
|
||||
@ -249,40 +212,8 @@ impl<'tcx> Const<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower a const param to a [`Const`].
|
||||
///
|
||||
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
|
||||
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
|
||||
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
|
||||
qpath
|
||||
else {
|
||||
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
|
||||
};
|
||||
|
||||
match tcx.named_bound_var(hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||
// Find the name and index of the const parameter by indexing the generics of
|
||||
// the parent item and construct a `ParamConst`.
|
||||
let item_def_id = tcx.parent(def_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
let name = tcx.item_name(def_id);
|
||||
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||
}
|
||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn try_from_lit_or_param(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Option<Self> {
|
||||
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = match &expr.kind {
|
||||
@ -321,7 +252,7 @@ impl<'tcx> Const<'tcx> {
|
||||
Err(e) => {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
expr.span,
|
||||
format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
|
||||
format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -414,20 +345,3 @@ impl<'tcx> Const<'tcx> {
|
||||
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_param_default<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) => ct,
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
};
|
||||
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -230,7 +230,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
|
||||
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
|
||||
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
|
||||
DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
|
||||
DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
|
||||
ty::AliasTermKind::UnevaluatedConst
|
||||
}
|
||||
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ pub use self::closure::{
|
||||
place_to_string_for_capture,
|
||||
};
|
||||
pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
@ -2249,7 +2249,6 @@ pub fn provide(providers: &mut Providers) {
|
||||
incoherent_impls: trait_def::incoherent_impls_provider,
|
||||
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
|
||||
traits: trait_def::traits_provider,
|
||||
const_param_default: consts::const_param_default,
|
||||
vtable_allocation: vtable::vtable_allocation_provider,
|
||||
..*providers
|
||||
};
|
||||
|
@ -641,9 +641,10 @@ impl<'a> Parser<'a> {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do an ASCII case-insensitive match, because all keywords are ASCII.
|
||||
if case == Case::Insensitive
|
||||
&& let Some((ident, IdentIsRaw::No)) = self.token.ident()
|
||||
&& ident.as_str().to_lowercase() == kw.as_str().to_lowercase()
|
||||
&& ident.as_str().eq_ignore_ascii_case(kw.as_str())
|
||||
{
|
||||
true
|
||||
} else {
|
||||
|
@ -126,6 +126,7 @@ impl<'k> StatCollector<'k> {
|
||||
});
|
||||
|
||||
let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
|
||||
let total_count = nodes.iter().map(|(_, node)| node.stats.count).sum();
|
||||
|
||||
eprintln!("{prefix} {title}");
|
||||
eprintln!(
|
||||
@ -167,7 +168,13 @@ impl<'k> StatCollector<'k> {
|
||||
}
|
||||
}
|
||||
eprintln!("{prefix} ----------------------------------------------------------------");
|
||||
eprintln!("{} {:<18}{:>10}", prefix, "Total", to_readable_str(total_size));
|
||||
eprintln!(
|
||||
"{} {:<18}{:>10} {:>14}",
|
||||
prefix,
|
||||
"Total",
|
||||
to_readable_str(total_size),
|
||||
to_readable_str(total_count),
|
||||
);
|
||||
eprintln!("{prefix}");
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ pub mod entry;
|
||||
mod errors;
|
||||
#[cfg(debug_assertions)]
|
||||
pub mod hir_id_validator;
|
||||
pub mod hir_stats;
|
||||
pub mod input_stats;
|
||||
mod lang_items;
|
||||
pub mod layout_test;
|
||||
mod lib_features;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#![allow(rustc::potential_query_instability, internal_features)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
|
@ -3,9 +3,10 @@ use std::hash::Hash;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sharded::{self, Sharded};
|
||||
use rustc_data_structures::sync::{Lock, OnceLock};
|
||||
use rustc_data_structures::sync::OnceLock;
|
||||
pub use rustc_data_structures::vec_cache::VecCache;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_index::Idx;
|
||||
use rustc_span::def_id::{DefId, DefIndex};
|
||||
|
||||
use crate::dep_graph::DepNodeIndex;
|
||||
@ -100,52 +101,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecCache<K: Idx, V> {
|
||||
cache: Lock<IndexVec<K, Option<(V, DepNodeIndex)>>>,
|
||||
}
|
||||
|
||||
impl<K: Idx, V> Default for VecCache<K, V> {
|
||||
fn default() -> Self {
|
||||
VecCache { cache: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> QueryCache for VecCache<K, V>
|
||||
where
|
||||
K: Eq + Idx + Copy + Debug,
|
||||
V: Copy,
|
||||
{
|
||||
type Key = K;
|
||||
type Value = V;
|
||||
|
||||
#[inline(always)]
|
||||
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
||||
let lock = self.cache.lock();
|
||||
if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn complete(&self, key: K, value: V, index: DepNodeIndex) {
|
||||
let mut lock = self.cache.lock();
|
||||
lock.insert(key, (value, index));
|
||||
}
|
||||
|
||||
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
|
||||
for (k, v) in self.cache.lock().iter_enumerated() {
|
||||
if let Some(v) = v {
|
||||
f(&k, &v.0, v.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefIdCache<V> {
|
||||
/// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
|
||||
/// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
|
||||
///
|
||||
/// The second element of the tuple is the set of keys actually present in the IndexVec, used
|
||||
/// for faster iteration in `iter()`.
|
||||
local: Lock<(IndexVec<DefIndex, Option<(V, DepNodeIndex)>>, Vec<DefIndex>)>,
|
||||
local: VecCache<DefIndex, V, DepNodeIndex>,
|
||||
foreign: DefaultCache<DefId, V>,
|
||||
}
|
||||
|
||||
@ -165,8 +124,7 @@ where
|
||||
#[inline(always)]
|
||||
fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> {
|
||||
if key.krate == LOCAL_CRATE {
|
||||
let cache = self.local.lock();
|
||||
cache.0.get(key.index).and_then(|v| *v)
|
||||
self.local.lookup(&key.index)
|
||||
} else {
|
||||
self.foreign.lookup(key)
|
||||
}
|
||||
@ -175,27 +133,39 @@ where
|
||||
#[inline]
|
||||
fn complete(&self, key: DefId, value: V, index: DepNodeIndex) {
|
||||
if key.krate == LOCAL_CRATE {
|
||||
let mut cache = self.local.lock();
|
||||
let (cache, present) = &mut *cache;
|
||||
let slot = cache.ensure_contains_elem(key.index, Default::default);
|
||||
if slot.is_none() {
|
||||
// FIXME: Only store the present set when running in incremental mode. `iter` is not
|
||||
// used outside of saving caches to disk and self-profile.
|
||||
present.push(key.index);
|
||||
}
|
||||
*slot = Some((value, index));
|
||||
self.local.complete(key.index, value, index)
|
||||
} else {
|
||||
self.foreign.complete(key, value, index)
|
||||
}
|
||||
}
|
||||
|
||||
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
|
||||
let guard = self.local.lock();
|
||||
let (cache, present) = &*guard;
|
||||
for &idx in present.iter() {
|
||||
let value = cache[idx].unwrap();
|
||||
f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1);
|
||||
}
|
||||
self.local.iter(&mut |key, value, index| {
|
||||
f(&DefId { krate: LOCAL_CRATE, index: *key }, value, index);
|
||||
});
|
||||
self.foreign.iter(f);
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> QueryCache for VecCache<K, V, DepNodeIndex>
|
||||
where
|
||||
K: Idx + Eq + Hash + Copy + Debug,
|
||||
V: Copy,
|
||||
{
|
||||
type Key = K;
|
||||
type Value = V;
|
||||
|
||||
#[inline(always)]
|
||||
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
||||
self.lookup(key)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn complete(&self, key: K, value: V, index: DepNodeIndex) {
|
||||
self.complete(key, value, index)
|
||||
}
|
||||
|
||||
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
|
||||
self.iter(f)
|
||||
}
|
||||
}
|
||||
|
@ -535,14 +535,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
filter_fn: &impl Fn(Res) -> bool,
|
||||
ctxt: Option<SyntaxContext>,
|
||||
) {
|
||||
for (key, resolution) in self.resolutions(module).borrow().iter() {
|
||||
if let Some(binding) = resolution.borrow().binding {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
|
||||
names.push(TypoSuggestion::typo_from_ident(key.ident, res));
|
||||
}
|
||||
module.for_each_child(self, |_this, ident, _ns, binding| {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == ident.span.ctxt()) {
|
||||
names.push(TypoSuggestion::typo_from_ident(ident, res));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Combines an error with provided span and emits it.
|
||||
|
@ -38,6 +38,12 @@ impl From<UsePrelude> for bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Shadowing {
|
||||
Restricted,
|
||||
Unrestricted,
|
||||
}
|
||||
|
||||
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
/// A generic scope visitor.
|
||||
/// Visits scopes in order to resolve some identifier in them or perform other actions.
|
||||
@ -311,13 +317,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
|
||||
// Walk backwards up the ribs in scope.
|
||||
let mut module = self.graph_root;
|
||||
for i in (0..ribs.len()).rev() {
|
||||
debug!("walk rib\n{:?}", ribs[i].bindings);
|
||||
for (i, rib) in ribs.iter().enumerate().rev() {
|
||||
debug!("walk rib\n{:?}", rib.bindings);
|
||||
// Use the rib kind to determine whether we are resolving parameters
|
||||
// (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
|
||||
let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
|
||||
if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident)
|
||||
{
|
||||
let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };
|
||||
if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {
|
||||
// The ident resolves to a type parameter or local variable.
|
||||
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
|
||||
i,
|
||||
@ -329,7 +334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
)));
|
||||
}
|
||||
|
||||
module = match ribs[i].kind {
|
||||
module = match rib.kind {
|
||||
RibKind::Module(module) => module,
|
||||
RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
|
||||
// If an invocation of this macro created `ident`, give up on `ident`
|
||||
@ -350,6 +355,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
Shadowing::Unrestricted,
|
||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||
ignore_binding,
|
||||
None,
|
||||
@ -494,7 +500,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
Scope::CrateRoot => {
|
||||
let root_ident = Ident::new(kw::PathRoot, ident.span);
|
||||
let root_module = this.resolve_crate_root(root_ident);
|
||||
let binding = this.resolve_ident_in_module_ext(
|
||||
let binding = this.resolve_ident_in_module(
|
||||
ModuleOrUniformRoot::Module(root_module),
|
||||
ident,
|
||||
ns,
|
||||
@ -516,12 +522,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
}
|
||||
Scope::Module(module, derive_fallback_lint_id) => {
|
||||
let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
|
||||
let binding = this.resolve_ident_in_module_unadjusted_ext(
|
||||
let binding = this.resolve_ident_in_module_unadjusted(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
adjusted_parent_scope,
|
||||
!matches!(scope_set, ScopeSet::Late(..)),
|
||||
if matches!(scope_set, ScopeSet::Late(..)) {
|
||||
Shadowing::Unrestricted
|
||||
} else {
|
||||
Shadowing::Restricted
|
||||
},
|
||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
@ -590,6 +600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
Shadowing::Unrestricted,
|
||||
None,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
@ -748,35 +759,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import)
|
||||
self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn resolve_ident_in_module(
|
||||
&mut self,
|
||||
module: ModuleOrUniformRoot<'ra>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<NameBinding<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(
|
||||
module,
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn resolve_ident_in_module_ext(
|
||||
&mut self,
|
||||
module: ModuleOrUniformRoot<'ra>,
|
||||
mut ident: Ident,
|
||||
@ -803,18 +791,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
// No adjustments
|
||||
}
|
||||
}
|
||||
self.resolve_ident_in_module_unadjusted_ext(
|
||||
self.resolve_ident_in_module_unadjusted(
|
||||
module,
|
||||
ident,
|
||||
ns,
|
||||
adjusted_parent_scope,
|
||||
false,
|
||||
Shadowing::Unrestricted,
|
||||
finalize,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
)
|
||||
}
|
||||
|
||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn resolve_ident_in_module_unadjusted(
|
||||
&mut self,
|
||||
@ -822,33 +812,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<NameBinding<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, Determinacy> {
|
||||
self.resolve_ident_in_module_unadjusted_ext(
|
||||
module,
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
false,
|
||||
finalize,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
|
||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn resolve_ident_in_module_unadjusted_ext(
|
||||
&mut self,
|
||||
module: ModuleOrUniformRoot<'ra>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
restricted_shadowing: bool,
|
||||
shadowing: Shadowing,
|
||||
finalize: Option<Finalize>,
|
||||
// This binding should be ignored during in-module resolution, so that we don't get
|
||||
// "self-confirming" import resolutions during import validation and checking.
|
||||
@ -858,7 +822,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
let module = match module {
|
||||
ModuleOrUniformRoot::Module(module) => module,
|
||||
ModuleOrUniformRoot::CrateRootAndExternPrelude => {
|
||||
assert!(!restricted_shadowing);
|
||||
assert_eq!(shadowing, Shadowing::Unrestricted);
|
||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||
ident,
|
||||
ScopeSet::AbsolutePath(ns),
|
||||
@ -871,7 +835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||
}
|
||||
ModuleOrUniformRoot::ExternPrelude => {
|
||||
assert!(!restricted_shadowing);
|
||||
assert_eq!(shadowing, Shadowing::Unrestricted);
|
||||
return if ns != TypeNS {
|
||||
Err((Determined, Weak::No))
|
||||
} else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
|
||||
@ -884,7 +848,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
};
|
||||
}
|
||||
ModuleOrUniformRoot::CurrentScope => {
|
||||
assert!(!restricted_shadowing);
|
||||
assert_eq!(shadowing, Shadowing::Unrestricted);
|
||||
if ns == TypeNS {
|
||||
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
|
||||
let module = self.resolve_crate_root(ident);
|
||||
@ -943,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
|
||||
// Forbid expanded shadowing to avoid time travel.
|
||||
if let Some(shadowed_glob) = resolution.shadowed_glob
|
||||
&& restricted_shadowing
|
||||
&& shadowing == Shadowing::Restricted
|
||||
&& binding.expansion != LocalExpnId::ROOT
|
||||
&& binding.res() != shadowed_glob.res()
|
||||
{
|
||||
@ -958,7 +922,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
});
|
||||
}
|
||||
|
||||
if !restricted_shadowing
|
||||
if shadowing == Shadowing::Unrestricted
|
||||
&& binding.expansion != LocalExpnId::ROOT
|
||||
&& let NameBindingKind::Import { import, .. } = binding.kind
|
||||
&& matches!(import.kind, ImportKind::MacroExport)
|
||||
@ -1047,13 +1011,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
) {
|
||||
Err(Determined) => continue,
|
||||
Err((Determined, _)) => continue,
|
||||
Ok(binding)
|
||||
if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::No)),
|
||||
Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::No)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1070,7 +1034,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
|
||||
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
|
||||
if let Some(binding) = binding {
|
||||
if binding.determined() || ns == MacroNS || restricted_shadowing {
|
||||
if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
|
||||
return check_usable(self, binding);
|
||||
} else {
|
||||
return Err((Undetermined, Weak::No));
|
||||
@ -1122,19 +1086,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ident,
|
||||
ns,
|
||||
adjusted_parent_scope,
|
||||
Shadowing::Unrestricted,
|
||||
None,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
);
|
||||
|
||||
match result {
|
||||
Err(Determined) => continue,
|
||||
Err((Determined, _)) => continue,
|
||||
Ok(binding)
|
||||
if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) =>
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::Yes)),
|
||||
Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::Yes)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,7 +1165,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
// Still doesn't deal with upvars
|
||||
if let Some(span) = finalize {
|
||||
let (span, resolution_error) = match item {
|
||||
None if rib_ident.as_str() == "self" => (span, LowercaseSelf),
|
||||
None if rib_ident.name == kw::SelfLower => {
|
||||
(span, LowercaseSelf)
|
||||
}
|
||||
None => {
|
||||
// If we have a `let name = expr;`, we have the span for
|
||||
// `name` and use that to see if it is followed by a type
|
||||
@ -1563,6 +1530,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
} else if let Some(ribs) = ribs
|
||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||
{
|
||||
|
@ -1688,9 +1688,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||
let mut outer_res = None;
|
||||
for rib in lifetime_rib_iter {
|
||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
|
||||
outer_res = Some(outer);
|
||||
break;
|
||||
|
@ -1082,8 +1082,6 @@ pub struct Resolver<'ra, 'tcx> {
|
||||
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
|
||||
|
||||
underscore_disambiguator: u32,
|
||||
/// Disambiguator for anonymous adts.
|
||||
empty_disambiguator: u32,
|
||||
|
||||
/// Maps glob imports to the names of items actually imported.
|
||||
glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
|
||||
@ -1462,7 +1460,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
module_children: Default::default(),
|
||||
trait_map: NodeMap::default(),
|
||||
underscore_disambiguator: 0,
|
||||
empty_disambiguator: 0,
|
||||
empty_module,
|
||||
module_map,
|
||||
block_map: Default::default(),
|
||||
@ -1809,12 +1806,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
assoc_item: Option<(Symbol, Namespace)>,
|
||||
) -> bool {
|
||||
match (trait_module, assoc_item) {
|
||||
(Some(trait_module), Some((name, ns))) => {
|
||||
self.resolutions(trait_module).borrow().iter().any(|resolution| {
|
||||
let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution;
|
||||
assoc_ns == ns && assoc_ident.name == name
|
||||
})
|
||||
}
|
||||
(Some(trait_module), Some((name, ns))) => self
|
||||
.resolutions(trait_module)
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
@ -1842,9 +1838,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
let disambiguator = if ident.name == kw::Underscore {
|
||||
self.underscore_disambiguator += 1;
|
||||
self.underscore_disambiguator
|
||||
} else if ident.name == kw::Empty {
|
||||
self.empty_disambiguator += 1;
|
||||
self.empty_disambiguator
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
@ -1805,8 +1805,6 @@ options! {
|
||||
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
|
||||
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"explicitly enable the `cfg(target_thread_local)` directive"),
|
||||
hir_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print some statistics about AST and HIR (default: no)"),
|
||||
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
|
||||
"generate human-readable, predictable names for codegen units (default: no)"),
|
||||
identify_regions: bool = (false, parse_bool, [UNTRACKED],
|
||||
@ -1838,7 +1836,7 @@ options! {
|
||||
inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"a default MIR inlining threshold (default: 50)"),
|
||||
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"gather statistics about the input (default: no)"),
|
||||
"print some statistics about AST and HIR (default: no)"),
|
||||
instrument_mcount: bool = (false, parse_bool, [TRACKED],
|
||||
"insert function instrument code for mcount-based tracing (default: no)"),
|
||||
instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
|
||||
|
@ -1226,6 +1226,7 @@ symbols! {
|
||||
min_const_generics,
|
||||
min_const_unsafe_fn,
|
||||
min_exhaustive_patterns,
|
||||
min_generic_const_args,
|
||||
min_specialization,
|
||||
min_type_alias_impl_trait,
|
||||
minnumf128,
|
||||
|
@ -677,7 +677,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the key-value pair corresponding to the supplied key.
|
||||
/// Returns the key-value pair corresponding to the supplied key. This is
|
||||
/// potentially useful:
|
||||
/// - for key types where non-identical keys can be considered equal;
|
||||
/// - for getting the `&K` stored key value from a borrowed `&Q` lookup key; or
|
||||
/// - for getting a reference to a key with the same lifetime as the collection.
|
||||
///
|
||||
/// The supplied key may be any borrowed form of the map's key type, but the ordering
|
||||
/// on the borrowed form *must* match the ordering on the key type.
|
||||
@ -685,12 +689,46 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp::Ordering;
|
||||
/// use std::collections::BTreeMap;
|
||||
///
|
||||
/// #[derive(Clone, Copy, Debug)]
|
||||
/// struct S {
|
||||
/// id: u32,
|
||||
/// # #[allow(unused)] // prevents a "field `name` is never read" error
|
||||
/// name: &'static str, // ignored by equality and ordering operations
|
||||
/// }
|
||||
///
|
||||
/// impl PartialEq for S {
|
||||
/// fn eq(&self, other: &S) -> bool {
|
||||
/// self.id == other.id
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Eq for S {}
|
||||
///
|
||||
/// impl PartialOrd for S {
|
||||
/// fn partial_cmp(&self, other: &S) -> Option<Ordering> {
|
||||
/// self.id.partial_cmp(&other.id)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Ord for S {
|
||||
/// fn cmp(&self, other: &S) -> Ordering {
|
||||
/// self.id.cmp(&other.id)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let j_a = S { id: 1, name: "Jessica" };
|
||||
/// let j_b = S { id: 1, name: "Jess" };
|
||||
/// let p = S { id: 2, name: "Paul" };
|
||||
/// assert_eq!(j_a, j_b);
|
||||
///
|
||||
/// let mut map = BTreeMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
|
||||
/// assert_eq!(map.get_key_value(&2), None);
|
||||
/// map.insert(j_a, "Paris");
|
||||
/// assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris")));
|
||||
/// assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case
|
||||
/// assert_eq!(map.get_key_value(&p), None);
|
||||
/// ```
|
||||
#[stable(feature = "map_get_key_value", since = "1.40.0")]
|
||||
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
|
||||
|
@ -215,7 +215,7 @@ pub macro const_panic {
|
||||
#[noinline]
|
||||
if const #[track_caller] #[inline] { // Inline this, to prevent codegen
|
||||
$crate::panic!($const_msg)
|
||||
} else #[track_caller] { // Do not inline this, it makes perf worse
|
||||
} else #[track_caller] #[cfg_attr(bootstrap, inline)] { // Do not inline this, it makes perf worse
|
||||
$crate::panic!($runtime_msg)
|
||||
}
|
||||
)
|
||||
|
@ -880,7 +880,11 @@ where
|
||||
self.base.get(k)
|
||||
}
|
||||
|
||||
/// Returns the key-value pair corresponding to the supplied key.
|
||||
/// Returns the key-value pair corresponding to the supplied key. This is
|
||||
/// potentially useful:
|
||||
/// - for key types where non-identical keys can be considered equal;
|
||||
/// - for getting the `&K` stored key value from a borrowed `&Q` lookup key; or
|
||||
/// - for getting a reference to a key with the same lifetime as the collection.
|
||||
///
|
||||
/// The supplied key may be any borrowed form of the map's key type, but
|
||||
/// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
|
||||
@ -890,11 +894,39 @@ where
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::hash::{Hash, Hasher};
|
||||
///
|
||||
/// #[derive(Clone, Copy, Debug)]
|
||||
/// struct S {
|
||||
/// id: u32,
|
||||
/// # #[allow(unused)] // prevents a "field `name` is never read" error
|
||||
/// name: &'static str, // ignored by equality and hashing operations
|
||||
/// }
|
||||
///
|
||||
/// impl PartialEq for S {
|
||||
/// fn eq(&self, other: &S) -> bool {
|
||||
/// self.id == other.id
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Eq for S {}
|
||||
///
|
||||
/// impl Hash for S {
|
||||
/// fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
/// self.id.hash(state);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let j_a = S { id: 1, name: "Jessica" };
|
||||
/// let j_b = S { id: 1, name: "Jess" };
|
||||
/// let p = S { id: 2, name: "Paul" };
|
||||
/// assert_eq!(j_a, j_b);
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
|
||||
/// assert_eq!(map.get_key_value(&2), None);
|
||||
/// map.insert(j_a, "Paris");
|
||||
/// assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris")));
|
||||
/// assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case
|
||||
/// assert_eq!(map.get_key_value(&p), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "map_get_key_value", since = "1.40.0")]
|
||||
|
@ -550,6 +550,9 @@ fn test_downgrade_observe() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
// FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
|
||||
// See <https://github.com/rust-lang/rust/issues/121950> for details.
|
||||
#[cfg_attr(all(miri, target_os = "macos"), ignore)]
|
||||
fn test_downgrade_atomic() {
|
||||
const NEW_VALUE: i32 = -1;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit ff9a4445038eae46fd095188740946808581bc0e
|
||||
Subproject commit e5e00aab0a8c8fa35fb7865e88fa82366f615c53
|
@ -1 +1 @@
|
||||
Subproject commit 2d482e203eb6d6e353814cf1415c5f94e590b9e0
|
||||
Subproject commit 915f9b319c2823f310430ecdecd86264a7870d7e
|
@ -1 +1 @@
|
||||
Subproject commit 456b904f791751892b01282fd2757904993c4c26
|
||||
Subproject commit eac89a3cbe6c4714e5029ae8b5a1c556fd4e8c42
|
@ -1 +1 @@
|
||||
Subproject commit da0f6dad767670da0e8cd5af8a7090db3272f626
|
||||
Subproject commit 41ccb0e6478305401dad92e8fd3d04a4304edb4c
|
@ -1 +1 @@
|
||||
Subproject commit 6a5accdaf10255882b1e6c59dfe5f1c79ac95484
|
||||
Subproject commit b679e71c2d66c6fe13e06b99ac61773b866213f0
|
@ -72,6 +72,8 @@
|
||||
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
|
||||
- [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
|
||||
- [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
|
||||
- [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
|
||||
- [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
|
||||
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
|
||||
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
|
||||
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
|
||||
|
@ -99,7 +99,7 @@ target | notes
|
||||
`powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
|
||||
[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
|
||||
[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
|
||||
`s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
|
||||
[`s390x-unknown-linux-gnu`](platform-support/s390x-unknown-linux-gnu.md) | S390x Linux (kernel 3.2, glibc 2.17)
|
||||
`x86_64-unknown-freebsd` | 64-bit FreeBSD
|
||||
`x86_64-unknown-illumos` | illumos
|
||||
`x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3
|
||||
@ -367,7 +367,7 @@ target | std | host | notes
|
||||
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
|
||||
[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android
|
||||
[`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
|
||||
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, musl 1.2.3)
|
||||
[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | | | S390x Linux (kernel 3.2, musl 1.2.3)
|
||||
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
|
||||
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+
|
||||
[`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64
|
||||
|
113
src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
Normal file
113
src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
Normal file
@ -0,0 +1,113 @@
|
||||
# `s390x-unknown-linux-gnu`
|
||||
|
||||
**Tier: 2 (with Host Tools)**
|
||||
|
||||
IBM z/Architecture (s390x) targets (including IBM Z and LinuxONE) running Linux.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- Ulrich Weigand, <ulrich.weigand@de.ibm.com>, [@uweigand](https://github.com/uweigand)
|
||||
- Josh Stone, <jistone@redhat.com>, [@cuviper](https://github.com/cuviper)
|
||||
|
||||
## Requirements
|
||||
|
||||
This target requires:
|
||||
|
||||
* Linux Kernel version 3.2 or later
|
||||
* glibc 2.17 or later
|
||||
|
||||
Code generated by the target uses the z/Architecture ISA assuming a minimum
|
||||
architecture level of z10 (Eighth Edition of the z/Architecture Principles
|
||||
of Operation), and is compliant with the s390x ELF ABI.
|
||||
|
||||
Reference material:
|
||||
|
||||
* [z/Architecture Principles of Operation][s390x-isa]
|
||||
* [z/Architecture ELF Application Binary Interface][s390x-abi]
|
||||
|
||||
[s390x-isa]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
|
||||
[s390x-abi]: https://github.com/IBM/s390x-abi
|
||||
|
||||
## Building the target
|
||||
|
||||
This target is distributed through `rustup`, and otherwise requires no
|
||||
special configuration.
|
||||
|
||||
If you need to build your own Rust for some reason though, the target can be
|
||||
enabled in `config.toml`. For example:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = ["s390x-unknown-linux-gnu"]
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
On a s390x Linux host, the `s390x-unknown-linux-gnu` target should be
|
||||
automatically installed and used by default.
|
||||
|
||||
On a non-s390x host, add the target:
|
||||
|
||||
```bash
|
||||
rustup target add s390x-unknown-linux-gnu
|
||||
```
|
||||
|
||||
Then cross compile crates with:
|
||||
|
||||
```bash
|
||||
cargo build --target s390x-unknown-linux-gnu
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
There are no special requirements for testing and running the target.
|
||||
For testing cross builds on the host, please refer to the "Cross-compilation
|
||||
toolchains and C code" section below.
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
Rust code built using the target is compatible with C code compiled with
|
||||
GCC or Clang using the `s390x-unknown-linux-gnu` target triple (via either
|
||||
native or cross-compilation).
|
||||
|
||||
On Ubuntu, a s390x cross-toolchain can be installed with:
|
||||
|
||||
```bash
|
||||
apt install gcc-s390x-linux-gnu g++-s390x-linux-gnu libc6-dev-s390x-cross
|
||||
```
|
||||
|
||||
Depending on your system, you may need to configure the target to use the GNU
|
||||
GCC linker. To use it, add the following to your `.cargo/config.toml`:
|
||||
|
||||
```toml
|
||||
[target.s390x-unknown-linux-gnu]
|
||||
linker = "s390x-linux-gnu-gcc"
|
||||
```
|
||||
|
||||
If your `s390x-linux-gnu-*` toolchain is not in your `PATH` you may need to
|
||||
configure additional settings:
|
||||
|
||||
```toml
|
||||
[target.s390x-unknown-linux-gnu]
|
||||
# Adjust the paths to point at your toolchain
|
||||
cc = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-gcc"
|
||||
cxx = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-g++"
|
||||
ar = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-ar"
|
||||
ranlib = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-ranlib"
|
||||
linker = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-gcc"
|
||||
```
|
||||
|
||||
To test cross compiled binaries on a non-s390x host, you can use
|
||||
[`qemu`](https://www.qemu.org/docs/master/system/target-s390x.html).
|
||||
On Ubuntu, a s390x emulator can be obtained with:
|
||||
|
||||
```bash
|
||||
apt install qemu-system-s390x
|
||||
```
|
||||
|
||||
Then, in `.cargo/config.toml` set the `runner`:
|
||||
|
||||
```toml
|
||||
[target.s390x-unknown-linux-gnu]
|
||||
runner = "qemu-s390x-static -L /usr/s390x-linux-gnu"
|
||||
```
|
@ -0,0 +1,83 @@
|
||||
# `s390x-unknown-linux-musl`
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
IBM z/Architecture (s390x) targets (including IBM Z and LinuxONE) running Linux.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- Ulrich Weigand, <ulrich.weigand@de.ibm.com>, [@uweigand](https://github.com/uweigand)
|
||||
|
||||
## Requirements
|
||||
|
||||
This target requires:
|
||||
|
||||
* Linux Kernel version 3.2 or later
|
||||
* musl 1.2.3 or later
|
||||
|
||||
Code generated by the target uses the z/Architecture ISA assuming a minimum
|
||||
architecture level of z10 (Eighth Edition of the z/Architecture Principles
|
||||
of Operation), and is compliant with the s390x ELF ABI.
|
||||
|
||||
Reference material:
|
||||
|
||||
* [z/Architecture Principles of Operation][s390x-isa]
|
||||
* [z/Architecture ELF Application Binary Interface][s390x-abi]
|
||||
|
||||
[s390x-isa]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
|
||||
[s390x-abi]: https://github.com/IBM/s390x-abi
|
||||
|
||||
## Building the target
|
||||
|
||||
Because it is Tier 3, Rust does not yet ship pre-compiled artifacts for this
|
||||
target.
|
||||
|
||||
Therefore, you can build Rust with support for the target by adding it to the
|
||||
target list in `config.toml`, a sample configuration is shown below.
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = ["s390x-unknown-linux-musl"]
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for
|
||||
this target, you will first need to build Rust with the target enabled (see
|
||||
"Building the target" above).
|
||||
|
||||
## Testing
|
||||
|
||||
There are no special requirements for testing and running the target.
|
||||
For testing cross builds on the host, please refer to the "Cross-compilation
|
||||
toolchains and C code" section below.
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
Rust code built using the target is compatible with C code compiled with
|
||||
GCC or Clang using the `s390x-unknown-linux-musl` target triple (via either
|
||||
native or cross-compilation).
|
||||
|
||||
Depending on your system, you may need to configure the target to use the GNU
|
||||
GCC linker. To use it, add the following to your `.cargo/config.toml`:
|
||||
|
||||
```toml
|
||||
[target.s390x-unknown-linux-musl]
|
||||
linker = "s390x-linux-musl-gcc"
|
||||
```
|
||||
|
||||
If your `s390x-linux-musl-*` toolchain is not in your `PATH` you may need to
|
||||
configure additional settings:
|
||||
|
||||
```toml
|
||||
[target.s390x-unknown-linux-musl]
|
||||
# Adjust the paths to point at your toolchain
|
||||
cc = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-gcc"
|
||||
cxx = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-g++"
|
||||
ar = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-ar"
|
||||
ranlib = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-ranlib"
|
||||
linker = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-gcc"
|
||||
```
|
||||
|
||||
To test cross compiled binaries on a non-s390x host, you can use
|
||||
[`qemu`](https://www.qemu.org/docs/master/system/target-s390x.html).
|
@ -447,32 +447,3 @@ This flag is **deprecated** and **has no effect**.
|
||||
Rustdoc only supports Rust source code and Markdown input formats. If the
|
||||
file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
|
||||
Otherwise, it assumes that the input file is Rust.
|
||||
|
||||
## `--test-builder`: `rustc`-like program to build tests
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc --test-builder /path/to/rustc src/lib.rs
|
||||
```
|
||||
|
||||
Rustdoc will use the provided program to compile tests instead of the default `rustc` program from
|
||||
the sysroot.
|
||||
|
||||
## `--test-builder-wrapper`: wrap calls to the test builder
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
|
||||
$ rustdoc \
|
||||
--test-builder-wrapper rustc-wrapper1 \
|
||||
--test-builder-wrapper rustc-wrapper2 \
|
||||
--test-builder rustc \
|
||||
src/lib.rs
|
||||
```
|
||||
|
||||
Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program.
|
||||
The first argument to the program will be the test builder program.
|
||||
|
||||
This flag can be passed multiple times to nest wrappers.
|
||||
|
@ -627,3 +627,36 @@ add the `--scrape-tests` flag.
|
||||
|
||||
This flag enables the generation of links in the source code pages which allow the reader
|
||||
to jump to a type definition.
|
||||
|
||||
### `--test-builder`: `rustc`-like program to build tests
|
||||
|
||||
* Tracking issue: [#102981](https://github.com/rust-lang/rust/issues/102981)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc --test-builder /path/to/rustc src/lib.rs
|
||||
```
|
||||
|
||||
Rustdoc will use the provided program to compile tests instead of the default `rustc` program from
|
||||
the sysroot.
|
||||
|
||||
### `--test-builder-wrapper`: wrap calls to the test builder
|
||||
|
||||
* Tracking issue: [#102981](https://github.com/rust-lang/rust/issues/102981)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc -Zunstable-options --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
|
||||
$ rustdoc -Zunstable-options \
|
||||
--test-builder-wrapper rustc-wrapper1 \
|
||||
--test-builder-wrapper rustc-wrapper2 \
|
||||
--test-builder rustc \
|
||||
src/lib.rs
|
||||
```
|
||||
|
||||
Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program.
|
||||
The first argument to the program will be the test builder program.
|
||||
|
||||
This flag can be passed multiple times to nest wrappers.
|
||||
|
@ -42,7 +42,8 @@ use rustc_errors::{FatalError, struct_span_code_err};
|
||||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
|
||||
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
|
||||
use rustc_middle::metadata::Reexport;
|
||||
use rustc_middle::middle::resolve_bound_vars as rbv;
|
||||
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
@ -435,10 +436,10 @@ fn clean_middle_term<'tcx>(
|
||||
fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
|
||||
match term {
|
||||
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
||||
hir::Term::Const(c) => Term::Constant(clean_middle_const(
|
||||
ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
|
||||
cx,
|
||||
)),
|
||||
hir::Term::Const(c) => {
|
||||
let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No);
|
||||
Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -625,7 +626,7 @@ fn clean_generic_param<'tcx>(
|
||||
(param.name.ident().name, GenericParamDefKind::Const {
|
||||
ty: Box::new(clean_ty(ty, cx)),
|
||||
default: default.map(|ct| {
|
||||
Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
|
||||
Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string())
|
||||
}),
|
||||
synthetic,
|
||||
})
|
||||
@ -1813,7 +1814,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
// `const_eval_poly` tries to first substitute generic parameters which
|
||||
// results in an ICE while manually constructing the constant and using `eval`
|
||||
// does nothing for `ConstKind::Param`.
|
||||
let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
|
||||
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
|
||||
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
|
||||
const_arg.kind
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ pub(crate) enum LinkFromSrc {
|
||||
/// It returns the `krate`, the source code files and the `span` correspondence map.
|
||||
///
|
||||
/// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't
|
||||
/// need the `span` context later on, only their position, so instead of keep a whole `Span`, we
|
||||
/// need the `span` context later on, only their position, so instead of keeping a whole `Span`, we
|
||||
/// only keep the `lo` and `hi`.
|
||||
pub(crate) fn collect_spans_and_sources(
|
||||
tcx: TyCtxt<'_>,
|
||||
@ -45,9 +45,9 @@ pub(crate) fn collect_spans_and_sources(
|
||||
include_sources: bool,
|
||||
generate_link_to_definition: bool,
|
||||
) -> (FxIndexMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
|
||||
let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
|
||||
|
||||
if include_sources {
|
||||
let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
|
||||
|
||||
if generate_link_to_definition {
|
||||
tcx.hir().walk_toplevel_module(&mut visitor);
|
||||
}
|
||||
@ -76,7 +76,22 @@ impl<'tcx> SpanMapVisitor<'tcx> {
|
||||
} else {
|
||||
LinkFromSrc::External(def_id)
|
||||
};
|
||||
self.matches.insert(path.span, link);
|
||||
// In case the path ends with generics, we remove them from the span.
|
||||
let span = path
|
||||
.segments
|
||||
.last()
|
||||
.map(|last| {
|
||||
// In `use` statements, the included item is not in the path segments.
|
||||
// However, it doesn't matter because you can't have generics on `use`
|
||||
// statements.
|
||||
if path.span.contains(last.ident.span) {
|
||||
path.span.with_hi(last.ident.span.hi())
|
||||
} else {
|
||||
path.span
|
||||
}
|
||||
})
|
||||
.unwrap_or(path.span);
|
||||
self.matches.insert(span, link);
|
||||
}
|
||||
Res::Local(_) => {
|
||||
if let Some(span) = self.tcx.hir().res_span(path.res) {
|
||||
|
@ -988,6 +988,12 @@ class VlqHexDecoder {
|
||||
}
|
||||
class RoaringBitmap {
|
||||
constructor(str) {
|
||||
// https://github.com/RoaringBitmap/RoaringFormatSpec
|
||||
//
|
||||
// Roaring bitmaps are used for flags that can be kept in their
|
||||
// compressed form, even when loaded into memory. This decoder
|
||||
// turns the containers into objects, but uses byte array
|
||||
// slices of the original format for the data payload.
|
||||
const strdecoded = atob(str);
|
||||
const u8array = new Uint8Array(strdecoded.length);
|
||||
for (let j = 0; j < strdecoded.length; ++j) {
|
||||
@ -1053,9 +1059,24 @@ class RoaringBitmap {
|
||||
contains(keyvalue) {
|
||||
const key = keyvalue >> 16;
|
||||
const value = keyvalue & 0xFFFF;
|
||||
for (let i = 0; i < this.keys.length; ++i) {
|
||||
if (this.keys[i] === key) {
|
||||
return this.containers[i].contains(value);
|
||||
// Binary search algorithm copied from
|
||||
// https://en.wikipedia.org/wiki/Binary_search#Procedure
|
||||
//
|
||||
// Format is required by specification to be sorted.
|
||||
// Because keys are 16 bits and unique, length can't be
|
||||
// bigger than 2**16, and because we have 32 bits of safe int,
|
||||
// left + right can't overflow.
|
||||
let left = 0;
|
||||
let right = this.keys.length - 1;
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const x = this.keys[mid];
|
||||
if (x < key) {
|
||||
left = mid + 1;
|
||||
} else if (x > key) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
return this.containers[mid].contains(value);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1068,11 +1089,23 @@ class RoaringBitmapRun {
|
||||
this.array = array;
|
||||
}
|
||||
contains(value) {
|
||||
const l = this.runcount * 4;
|
||||
for (let i = 0; i < l; i += 4) {
|
||||
// Binary search algorithm copied from
|
||||
// https://en.wikipedia.org/wiki/Binary_search#Procedure
|
||||
//
|
||||
// Since runcount is stored as 16 bits, left + right
|
||||
// can't overflow.
|
||||
let left = 0;
|
||||
let right = this.runcount - 1;
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const i = mid * 4;
|
||||
const start = this.array[i] | (this.array[i + 1] << 8);
|
||||
const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8);
|
||||
if (value >= start && value <= (start + lenm1)) {
|
||||
if ((start + lenm1) < value) {
|
||||
left = mid + 1;
|
||||
} else if (start > value) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1085,10 +1118,22 @@ class RoaringBitmapArray {
|
||||
this.array = array;
|
||||
}
|
||||
contains(value) {
|
||||
const l = this.cardinality * 2;
|
||||
for (let i = 0; i < l; i += 2) {
|
||||
const start = this.array[i] | (this.array[i + 1] << 8);
|
||||
if (value === start) {
|
||||
// Binary search algorithm copied from
|
||||
// https://en.wikipedia.org/wiki/Binary_search#Procedure
|
||||
//
|
||||
// Since cardinality can't be higher than 4096, left + right
|
||||
// cannot overflow.
|
||||
let left = 0;
|
||||
let right = this.cardinality - 1;
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const i = mid * 2;
|
||||
const x = this.array[i] | (this.array[i + 1] << 8);
|
||||
if (x < value) {
|
||||
left = mid + 1;
|
||||
} else if (x > value) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 69e595908e2c420e7f0d1be34e6c5b984c8cfb84
|
||||
Subproject commit 66221abdeca2002d318fde6efff516aab091df0e
|
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
@ -521,15 +521,15 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
||||
|
||||
[[package]]
|
||||
name = "xshell"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
|
||||
checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d"
|
||||
dependencies = [
|
||||
"xshell-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xshell-macros"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
|
||||
checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547"
|
||||
|
17
tests/crashes/132985.rs
Normal file
17
tests/crashes/132985.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//@ known-bug: #132985
|
||||
//@ aux-build:aux132985.rs
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
extern crate aux132985;
|
||||
use aux132985::Foo;
|
||||
|
||||
fn bar<const N: Foo>() {}
|
||||
|
||||
fn baz() {
|
||||
bar::<{ Foo }>();
|
||||
}
|
||||
|
||||
fn main() {}
|
6
tests/crashes/auxiliary/aux132985.rs
Normal file
6
tests/crashes/auxiliary/aux132985.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||
pub struct Foo;
|
14
tests/rustdoc/link-on-path-with-generics.rs
Normal file
14
tests/rustdoc/link-on-path-with-generics.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// This test ensures that paths with generics still get their link to their definition
|
||||
// correctly generated.
|
||||
|
||||
//@ compile-flags: -Zunstable-options --generate-link-to-definition
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'src/foo/link-on-path-with-generics.rs.html'
|
||||
|
||||
pub struct Soyo<T>(T);
|
||||
pub struct Saya;
|
||||
|
||||
//@ has - '//pre[@class="rust"]//a[@href="#9"]' 'Soyo'
|
||||
//@ has - '//pre[@class="rust"]//a[@href="#10"]' 'Saya'
|
||||
pub fn bar<T>(s: Soyo<T>, x: Saya) {}
|
11
tests/ui/check-cfg/auxiliary/cfg_macro.rs
Normal file
11
tests/ui/check-cfg/auxiliary/cfg_macro.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Inspired by https://github.com/rust-lang/cargo/issues/14775
|
||||
|
||||
pub fn my_lib_func() {}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! my_lib_macro {
|
||||
() => {
|
||||
#[cfg(my_lib_cfg)]
|
||||
$crate::my_lib_func()
|
||||
};
|
||||
}
|
12
tests/ui/check-cfg/report-in-external-macros.rs
Normal file
12
tests/ui/check-cfg/report-in-external-macros.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// This test checks that we emit the `unexpected_cfgs` lint even in code
|
||||
// coming from an external macro.
|
||||
|
||||
//@ check-pass
|
||||
//@ no-auto-check-cfg
|
||||
//@ aux-crate: cfg_macro=cfg_macro.rs
|
||||
//@ compile-flags: --check-cfg=cfg()
|
||||
|
||||
fn main() {
|
||||
cfg_macro::my_lib_macro!();
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
}
|
14
tests/ui/check-cfg/report-in-external-macros.stderr
Normal file
14
tests/ui/check-cfg/report-in-external-macros.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
warning: unexpected `cfg` condition name: `my_lib_cfg`
|
||||
--> $DIR/report-in-external-macros.rs:10:5
|
||||
|
|
||||
LL | cfg_macro::my_lib_macro!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
|
||||
= help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
= note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
6
tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
Normal file
6
tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||
pub struct Foo;
|
7
tests/ui/const-generics/using-static-as-const-arg.rs
Normal file
7
tests/ui/const-generics/using-static-as-const-arg.rs
Normal file
@ -0,0 +1,7 @@
|
||||
//@ check-pass
|
||||
|
||||
pub static STATIC: u32 = 0;
|
||||
pub struct Foo<const N: u32>;
|
||||
pub const FOO: Foo<{STATIC}> = Foo;
|
||||
|
||||
fn main() {}
|
15
tests/ui/const-generics/xcrate-const-ctor-b.rs
Normal file
15
tests/ui/const-generics/xcrate-const-ctor-b.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ check-pass
|
||||
//@ aux-build:xcrate-const-ctor-a.rs
|
||||
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
extern crate xcrate_const_ctor_a;
|
||||
use xcrate_const_ctor_a::Foo;
|
||||
|
||||
fn bar<const N: Foo>() {}
|
||||
|
||||
fn baz() {
|
||||
bar::<{ Foo }>();
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,3 +1,5 @@
|
||||
//@ reference: attributes.diagnostic.namespace.unknown-invalid-syntax
|
||||
|
||||
#![deny(unknown_or_malformed_diagnostic_attributes)]
|
||||
|
||||
#[diagnostic::unknown_attribute]
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: unknown diagnostic attribute
|
||||
--> $DIR/deny_malformed_attribute.rs:3:15
|
||||
--> $DIR/deny_malformed_attribute.rs:5:15
|
||||
|
|
||||
LL | #[diagnostic::unknown_attribute]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/deny_malformed_attribute.rs:1:9
|
||||
--> $DIR/deny_malformed_attribute.rs:3:9
|
||||
|
|
||||
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,5 +1,6 @@
|
||||
//@ edition:2021
|
||||
//@ aux-build:bad_on_unimplemented.rs
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.syntax
|
||||
|
||||
// Do not ICE when encountering a malformed `#[diagnostic::on_unimplemented]` annotation in a
|
||||
// dependency when incorrectly used (#124651).
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::MissingAttr` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:22:18
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:23:18
|
||||
|
|
||||
LL | missing_attr(());
|
||||
| ------------ ^^ the trait `bad_on_unimplemented::MissingAttr` is not implemented for `()`
|
||||
@ -7,13 +7,13 @@ LL | missing_attr(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `missing_attr`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:11:20
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:12:20
|
||||
|
|
||||
LL | fn missing_attr<T: MissingAttr>(_: T) {}
|
||||
| ^^^^^^^^^^^ required by this bound in `missing_attr`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::DuplicateAttr` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:23:20
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:24:20
|
||||
|
|
||||
LL | duplicate_attr(());
|
||||
| -------------- ^^ a
|
||||
@ -22,13 +22,13 @@ LL | duplicate_attr(());
|
||||
|
|
||||
= help: the trait `bad_on_unimplemented::DuplicateAttr` is not implemented for `()`
|
||||
note: required by a bound in `duplicate_attr`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:12:22
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:13:22
|
||||
|
|
||||
LL | fn duplicate_attr<T: DuplicateAttr>(_: T) {}
|
||||
| ^^^^^^^^^^^^^ required by this bound in `duplicate_attr`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::NotMetaList` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:24:19
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:25:19
|
||||
|
|
||||
LL | not_meta_list(());
|
||||
| ------------- ^^ the trait `bad_on_unimplemented::NotMetaList` is not implemented for `()`
|
||||
@ -36,13 +36,13 @@ LL | not_meta_list(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `not_meta_list`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:13:21
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:14:21
|
||||
|
|
||||
LL | fn not_meta_list<T: NotMetaList>(_: T) {}
|
||||
| ^^^^^^^^^^^ required by this bound in `not_meta_list`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::Empty` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:25:11
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:26:11
|
||||
|
|
||||
LL | empty(());
|
||||
| ----- ^^ the trait `bad_on_unimplemented::Empty` is not implemented for `()`
|
||||
@ -50,13 +50,13 @@ LL | empty(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `empty`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:14:13
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:15:13
|
||||
|
|
||||
LL | fn empty<T: Empty>(_: T) {}
|
||||
| ^^^^^ required by this bound in `empty`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::WrongDelim` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:26:17
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:27:17
|
||||
|
|
||||
LL | wrong_delim(());
|
||||
| ----------- ^^ the trait `bad_on_unimplemented::WrongDelim` is not implemented for `()`
|
||||
@ -64,13 +64,13 @@ LL | wrong_delim(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `wrong_delim`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:15:19
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:16:19
|
||||
|
|
||||
LL | fn wrong_delim<T: WrongDelim>(_: T) {}
|
||||
| ^^^^^^^^^^ required by this bound in `wrong_delim`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::BadFormatter<()>` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:27:19
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:28:19
|
||||
|
|
||||
LL | bad_formatter(());
|
||||
| ------------- ^^ ()
|
||||
@ -79,13 +79,13 @@ LL | bad_formatter(());
|
||||
|
|
||||
= help: the trait `bad_on_unimplemented::BadFormatter<()>` is not implemented for `()`
|
||||
note: required by a bound in `bad_formatter`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:16:21
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:17:21
|
||||
|
|
||||
LL | fn bad_formatter<T: BadFormatter<()>>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `bad_formatter`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::NoImplicitArgs` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:28:22
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:29:22
|
||||
|
|
||||
LL | no_implicit_args(());
|
||||
| ---------------- ^^ test {}
|
||||
@ -94,13 +94,13 @@ LL | no_implicit_args(());
|
||||
|
|
||||
= help: the trait `bad_on_unimplemented::NoImplicitArgs` is not implemented for `()`
|
||||
note: required by a bound in `no_implicit_args`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:17:24
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:18:24
|
||||
|
|
||||
LL | fn no_implicit_args<T: NoImplicitArgs>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^ required by this bound in `no_implicit_args`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::MissingArg` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:29:17
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:30:17
|
||||
|
|
||||
LL | missing_arg(());
|
||||
| ----------- ^^ {missing}
|
||||
@ -109,13 +109,13 @@ LL | missing_arg(());
|
||||
|
|
||||
= help: the trait `bad_on_unimplemented::MissingArg` is not implemented for `()`
|
||||
note: required by a bound in `missing_arg`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:18:19
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:19:19
|
||||
|
|
||||
LL | fn missing_arg<T: MissingArg>(_: T) {}
|
||||
| ^^^^^^^^^^ required by this bound in `missing_arg`
|
||||
|
||||
error[E0277]: the trait bound `(): bad_on_unimplemented::BadArg` is not satisfied
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:30:13
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:31:13
|
||||
|
|
||||
LL | bad_arg(());
|
||||
| ------- ^^ {_}
|
||||
@ -124,7 +124,7 @@ LL | bad_arg(());
|
||||
|
|
||||
= help: the trait `bad_on_unimplemented::BadArg` is not implemented for `()`
|
||||
note: required by a bound in `bad_arg`
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:19:15
|
||||
--> $DIR/malformed_foreign_on_unimplemented.rs:20:15
|
||||
|
|
||||
LL | fn bad_arg<T: BadArg>(_: T) {}
|
||||
| ^^^^^^ required by this bound in `bad_arg`
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ check-pass
|
||||
//@ reference: attributes.diagnostic.namespace.unknown-invalid-syntax
|
||||
#[diagnostic::non_existing_attribute]
|
||||
//~^WARN unknown diagnostic attribute
|
||||
pub trait Bar {
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unknown diagnostic attribute
|
||||
--> $DIR/non_existing_attributes_accepted.rs:2:15
|
||||
--> $DIR/non_existing_attributes_accepted.rs:3:15
|
||||
|
|
||||
LL | #[diagnostic::non_existing_attribute]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute]
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: unknown diagnostic attribute
|
||||
--> $DIR/non_existing_attributes_accepted.rs:7:15
|
||||
--> $DIR/non_existing_attributes_accepted.rs:8:15
|
||||
|
|
||||
LL | #[diagnostic::non_existing_attribute(with_option = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,3 +1,4 @@
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.invalid-string
|
||||
#[diagnostic::on_unimplemented(message = "{{Test } thing")]
|
||||
//~^WARN unmatched `}` found
|
||||
//~|WARN unmatched `}` found
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unmatched `}` found
|
||||
--> $DIR/broken_format.rs:1:32
|
||||
--> $DIR/broken_format.rs:2:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: positional format arguments are not allowed here
|
||||
--> $DIR/broken_format.rs:6:32
|
||||
--> $DIR/broken_format.rs:7:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {}")]
|
||||
= help: only named format arguments with the name of one of the generic types are allowed in this context
|
||||
|
||||
warning: positional format arguments are not allowed here
|
||||
--> $DIR/broken_format.rs:11:32
|
||||
--> $DIR/broken_format.rs:12:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
|
||||
= help: only named format arguments with the name of one of the generic types are allowed in this context
|
||||
|
||||
warning: invalid format specifier
|
||||
--> $DIR/broken_format.rs:16:32
|
||||
--> $DIR/broken_format.rs:17:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,19 +31,19 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
|
||||
= help: no format specifier are supported in this position
|
||||
|
||||
warning: expected `}`, found `!`
|
||||
--> $DIR/broken_format.rs:21:32
|
||||
--> $DIR/broken_format.rs:22:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unmatched `}` found
|
||||
--> $DIR/broken_format.rs:21:32
|
||||
--> $DIR/broken_format.rs:22:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unmatched `}` found
|
||||
--> $DIR/broken_format.rs:1:32
|
||||
--> $DIR/broken_format.rs:2:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -51,7 +51,7 @@ LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: {{Test } thing
|
||||
--> $DIR/broken_format.rs:35:13
|
||||
--> $DIR/broken_format.rs:36:13
|
||||
|
|
||||
LL | check_1(());
|
||||
| ------- ^^ the trait `ImportantTrait1` is not implemented for `()`
|
||||
@ -59,18 +59,18 @@ LL | check_1(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/broken_format.rs:4:1
|
||||
--> $DIR/broken_format.rs:5:1
|
||||
|
|
||||
LL | trait ImportantTrait1 {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `check_1`
|
||||
--> $DIR/broken_format.rs:28:20
|
||||
--> $DIR/broken_format.rs:29:20
|
||||
|
|
||||
LL | fn check_1(_: impl ImportantTrait1) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check_1`
|
||||
|
||||
warning: positional format arguments are not allowed here
|
||||
--> $DIR/broken_format.rs:6:32
|
||||
--> $DIR/broken_format.rs:7:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
@ -79,7 +79,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Test {}
|
||||
--> $DIR/broken_format.rs:37:13
|
||||
--> $DIR/broken_format.rs:38:13
|
||||
|
|
||||
LL | check_2(());
|
||||
| ------- ^^ the trait `ImportantTrait2` is not implemented for `()`
|
||||
@ -87,18 +87,18 @@ LL | check_2(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/broken_format.rs:9:1
|
||||
--> $DIR/broken_format.rs:10:1
|
||||
|
|
||||
LL | trait ImportantTrait2 {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `check_2`
|
||||
--> $DIR/broken_format.rs:29:20
|
||||
--> $DIR/broken_format.rs:30:20
|
||||
|
|
||||
LL | fn check_2(_: impl ImportantTrait2) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check_2`
|
||||
|
||||
warning: positional format arguments are not allowed here
|
||||
--> $DIR/broken_format.rs:11:32
|
||||
--> $DIR/broken_format.rs:12:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -107,7 +107,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Test {1}
|
||||
--> $DIR/broken_format.rs:39:13
|
||||
--> $DIR/broken_format.rs:40:13
|
||||
|
|
||||
LL | check_3(());
|
||||
| ------- ^^ the trait `ImportantTrait3` is not implemented for `()`
|
||||
@ -115,18 +115,18 @@ LL | check_3(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/broken_format.rs:14:1
|
||||
--> $DIR/broken_format.rs:15:1
|
||||
|
|
||||
LL | trait ImportantTrait3 {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `check_3`
|
||||
--> $DIR/broken_format.rs:30:20
|
||||
--> $DIR/broken_format.rs:31:20
|
||||
|
|
||||
LL | fn check_3(_: impl ImportantTrait3) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check_3`
|
||||
|
||||
warning: invalid format specifier
|
||||
--> $DIR/broken_format.rs:16:32
|
||||
--> $DIR/broken_format.rs:17:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -135,7 +135,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Test ()
|
||||
--> $DIR/broken_format.rs:41:13
|
||||
--> $DIR/broken_format.rs:42:13
|
||||
|
|
||||
LL | check_4(());
|
||||
| ------- ^^ the trait `ImportantTrait4` is not implemented for `()`
|
||||
@ -143,18 +143,18 @@ LL | check_4(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/broken_format.rs:19:1
|
||||
--> $DIR/broken_format.rs:20:1
|
||||
|
|
||||
LL | trait ImportantTrait4 {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `check_4`
|
||||
--> $DIR/broken_format.rs:31:20
|
||||
--> $DIR/broken_format.rs:32:20
|
||||
|
|
||||
LL | fn check_4(_: impl ImportantTrait4) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check_4`
|
||||
|
||||
warning: expected `}`, found `!`
|
||||
--> $DIR/broken_format.rs:21:32
|
||||
--> $DIR/broken_format.rs:22:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -162,7 +162,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: unmatched `}` found
|
||||
--> $DIR/broken_format.rs:21:32
|
||||
--> $DIR/broken_format.rs:22:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -170,7 +170,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Test {Self:!}
|
||||
--> $DIR/broken_format.rs:43:13
|
||||
--> $DIR/broken_format.rs:44:13
|
||||
|
|
||||
LL | check_5(());
|
||||
| ------- ^^ the trait `ImportantTrait5` is not implemented for `()`
|
||||
@ -178,12 +178,12 @@ LL | check_5(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/broken_format.rs:26:1
|
||||
--> $DIR/broken_format.rs:27:1
|
||||
|
|
||||
LL | trait ImportantTrait5 {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `check_5`
|
||||
--> $DIR/broken_format.rs:32:20
|
||||
--> $DIR/broken_format.rs:33:20
|
||||
|
|
||||
LL | fn check_5(_: impl ImportantTrait5) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check_5`
|
||||
|
@ -1,3 +1,5 @@
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.intro
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.keys
|
||||
#[diagnostic::on_unimplemented(message = "my message", label = "my label", note = "my note")]
|
||||
pub trait ProviderLt {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0599]: my message
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:15:7
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:17:7
|
||||
|
|
||||
LL | struct B;
|
||||
| -------- method `request` not found for this struct because it doesn't satisfy `B: ProviderExt` or `B: ProviderLt`
|
||||
@ -8,7 +8,7 @@ LL | B.request();
|
||||
| ^^^^^^^ my label
|
||||
|
|
||||
note: trait bound `B: ProviderLt` was not satisfied
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:10:18
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:12:18
|
||||
|
|
||||
LL | impl<T: ?Sized + ProviderLt> ProviderExt for T {}
|
||||
| ^^^^^^^^^^ ----------- -
|
||||
@ -16,13 +16,13 @@ LL | impl<T: ?Sized + ProviderLt> ProviderExt for T {}
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: my note
|
||||
note: the trait `ProviderLt` must be implemented
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:2:1
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:4:1
|
||||
|
|
||||
LL | pub trait ProviderLt {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `ProviderExt` defines an item `request`, perhaps you need to implement it
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:4:1
|
||||
--> $DIR/custom-on-unimplemented-diagnostic.rs:6:1
|
||||
|
|
||||
LL | pub trait ProviderExt {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
@ -1,3 +1,7 @@
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.format-parameters
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.keys
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.syntax
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.invalid-formats
|
||||
#[diagnostic::on_unimplemented(
|
||||
on(_Self = "&str"),
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:26:1
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
|
||||
|
|
||||
LL | on(_Self = "&str"),
|
||||
| ^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -15,7 +15,7 @@ LL | on(_Self = "&str"),
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:12:5
|
||||
|
|
||||
LL | parent_label = "in this scope",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -23,7 +23,7 @@ LL | parent_label = "in this scope",
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:5
|
||||
|
|
||||
LL | append_const_msg
|
||||
| ^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -31,7 +31,7 @@ LL | append_const_msg
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:21:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
| ^^^^^^^^^^^ invalid option found here
|
||||
@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: there is no parameter `from_desugaring` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -47,7 +47,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `direct` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -55,7 +55,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `cause` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -63,7 +63,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `integral` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -71,7 +71,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `integer` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -79,7 +79,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `float` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -87,7 +87,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `_Self` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -95,7 +95,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `crate_local` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -103,7 +103,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `Trait` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -111,7 +111,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `ItemContext` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -119,7 +119,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
|
||||
|
|
||||
LL | on(_Self = "&str"),
|
||||
| ^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -128,7 +128,7 @@ LL | on(_Self = "&str"),
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:12:5
|
||||
|
|
||||
LL | parent_label = "in this scope",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -137,7 +137,7 @@ LL | parent_label = "in this scope",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:5
|
||||
|
|
||||
LL | append_const_msg
|
||||
| ^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -146,7 +146,7 @@ LL | append_const_msg
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: trait has `()` and `i32` as params
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
|
||||
|
|
||||
LL | takes_foo(());
|
||||
| --------- ^^ trait has `()` and `i32` as params
|
||||
@ -156,18 +156,18 @@ LL | takes_foo(());
|
||||
= help: the trait `Foo<i32>` is not implemented for `()`
|
||||
= note: trait has `()` and `i32` as params
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:1
|
||||
|
|
||||
LL | trait Foo<T> {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: required by a bound in `takes_foo`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
|
||||
|
|
||||
LL | fn takes_foo(_: impl Foo<i32>) {}
|
||||
| ^^^^^^^^ required by this bound in `takes_foo`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:21:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
| ^^^^^^^^^^^ invalid option found here
|
||||
@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `(): Bar` is not satisfied
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
|
||||
|
|
||||
LL | takes_bar(());
|
||||
| --------- ^^ the trait `Bar` is not implemented for `()`
|
||||
@ -185,13 +185,13 @@ LL | takes_bar(());
|
||||
|
|
||||
= help: the trait `Bar` is implemented for `i32`
|
||||
note: required by a bound in `takes_bar`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:22
|
||||
|
|
||||
LL | fn takes_bar(_: impl Bar) {}
|
||||
| ^^^ required by this bound in `takes_bar`
|
||||
|
||||
warning: there is no parameter `from_desugaring` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -200,7 +200,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `direct` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -209,7 +209,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `cause` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -218,7 +218,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `integral` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -227,7 +227,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `integer` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -236,7 +236,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `float` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -245,7 +245,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `_Self` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -254,7 +254,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `crate_local` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -263,7 +263,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `Trait` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -272,7 +272,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `ItemContext` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -281,7 +281,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:67:15
|
||||
|
|
||||
LL | takes_baz(());
|
||||
| --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
|
||||
@ -290,12 +290,12 @@ LL | takes_baz(());
|
||||
|
|
||||
= help: the trait `Baz` is not implemented for `()`
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:1
|
||||
|
|
||||
LL | trait Baz {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `takes_baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:60:22
|
||||
|
|
||||
LL | fn takes_baz(_: impl Baz) {}
|
||||
| ^^^ required by this bound in `takes_baz`
|
||||
|
@ -1,3 +1,5 @@
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.syntax
|
||||
//@ reference: attributes.diagnostic.on_unimplemented.unknown-keys
|
||||
#[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
//~|WARN malformed `on_unimplemented` attribute
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Baz")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")]
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
|
||||
| ^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented = "boom"]
|
||||
| ^^^^^^^^ invalid option found here
|
||||
@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"]
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: missing options for `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented]
|
||||
= help: at least one of the `message`, `note` and `label` options are expected
|
||||
|
||||
warning: there is no parameter `DoesNotExist` on trait `Test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `i32: Foo` is not satisfied
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
|
||||
|
|
||||
LL | take_foo(1_i32);
|
||||
| -------- ^^^^^ the trait `Foo` is not implemented for `i32`
|
||||
@ -72,18 +72,18 @@ LL | take_foo(1_i32);
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
|
||||
|
|
||||
LL | trait Foo {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `take_foo`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
|
||||
|
|
||||
LL | fn take_foo(_: impl Foo) {}
|
||||
| ^^^ required by this bound in `take_foo`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
|
||||
| ^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Boom
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
|
||||
|
|
||||
LL | take_baz(1_i32);
|
||||
| -------- ^^^^^ the trait `Baz` is not implemented for `i32`
|
||||
@ -100,18 +100,18 @@ LL | take_baz(1_i32);
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1
|
||||
|
|
||||
LL | trait Baz {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `take_baz`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
|
||||
|
|
||||
LL | fn take_baz(_: impl Baz) {}
|
||||
| ^^^ required by this bound in `take_baz`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Boom
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
|
||||
|
|
||||
LL | take_boom(1_i32);
|
||||
| --------- ^^^^^ the trait `Boom` is not implemented for `i32`
|
||||
@ -128,18 +128,18 @@ LL | take_boom(1_i32);
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1
|
||||
|
|
||||
LL | trait Boom {}
|
||||
| ^^^^^^^^^^
|
||||
note: required by a bound in `take_boom`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
|
||||
|
|
||||
LL | fn take_boom(_: impl Boom) {}
|
||||
| ^^^^ required by this bound in `take_boom`
|
||||
|
||||
warning: missing options for `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `i32: Whatever` is not satisfied
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
|
||||
|
|
||||
LL | take_whatever(1_i32);
|
||||
| ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
|
||||
@ -156,18 +156,18 @@ LL | take_whatever(1_i32);
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1
|
||||
|
|
||||
LL | trait Whatever {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: required by a bound in `take_whatever`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
|
||||
|
|
||||
LL | fn take_whatever(_: impl Whatever) {}
|
||||
| ^^^^^^^^ required by this bound in `take_whatever`
|
||||
|
||||
warning: there is no parameter `DoesNotExist` on trait `Test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: {DoesNotExist}
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
|
||||
|
|
||||
LL | take_test(());
|
||||
| --------- ^^ the trait `Test` is not implemented for `()`
|
||||
@ -184,12 +184,12 @@ LL | take_test(());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
|
||||
|
|
||||
LL | trait Test {}
|
||||
| ^^^^^^^^^^
|
||||
note: required by a bound in `take_test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
|
||||
|
|
||||
LL | fn take_test(_: impl Test) {}
|
||||
| ^^^^ required by this bound in `take_test`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user