Auto merge of #3727 - RalfJung:rustup, r=RalfJung
Rustup To unblock https://github.com/rust-lang/miri/pull/3688
This commit is contained in:
commit
3ca56a34bd
665 changed files with 9525 additions and 6702 deletions
2
.ignore
Normal file
2
.ignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Make vscode *not* count `config.toml` as ignored, so it is included in search
|
||||
!/config.toml
|
||||
|
|
@ -36,6 +36,7 @@ Files: compiler/*
|
|||
.gitignore
|
||||
.gitmodules
|
||||
.mailmap
|
||||
.ignore
|
||||
Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT or Apache-2.0
|
||||
|
||||
|
|
|
|||
12
Cargo.lock
12
Cargo.lock
|
|
@ -3401,6 +3401,7 @@ name = "run_make_support"
|
|||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"ar",
|
||||
"bstr",
|
||||
"gimli 0.28.1",
|
||||
"object 0.34.0",
|
||||
"regex",
|
||||
|
|
@ -3460,6 +3461,13 @@ dependencies = [
|
|||
"stable_mir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-perf-wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon"
|
||||
version = "0.5.0"
|
||||
|
|
@ -4752,8 +4760,6 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
|
|||
name = "rustc_trait_selection"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"derivative",
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
|
|
@ -4762,7 +4768,6 @@ dependencies = [
|
|||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
|
|
@ -4775,7 +4780,6 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"rustc_transmute",
|
||||
"rustc_type_ir",
|
||||
"rustc_type_ir_macros",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ members = [
|
|||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/opt-dist",
|
||||
"src/tools/coverage-dump",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ParamMode::Optional,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
// Method calls can't have bound modifiers
|
||||
None,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
owner: NodeId,
|
||||
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
||||
) {
|
||||
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
|
||||
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index);
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
for (def_id, info) in lctx.children {
|
||||
|
|
@ -190,6 +190,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, (ty, body_id)) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -221,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) =
|
||||
this.lower_generics(generics, header.constness, id, itctx, |this| {
|
||||
this.lower_generics(generics, header.constness, false, id, itctx, |this| {
|
||||
this.lower_fn_decl(
|
||||
decl,
|
||||
id,
|
||||
|
|
@ -265,6 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
|
|
@ -293,6 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, variants) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -307,6 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, struct_def) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, struct_def),
|
||||
|
|
@ -317,6 +321,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, vdata) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, vdata),
|
||||
|
|
@ -348,12 +353,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, *constness, id, itctx, |this| {
|
||||
self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: match *constness {
|
||||
Const::Yes(span) => BoundConstness::Maybe(span),
|
||||
Const::No => BoundConstness::Never,
|
||||
},
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
|
|
@ -389,6 +391,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
||||
};
|
||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||
constness: self.lower_constness(*constness),
|
||||
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
||||
polarity,
|
||||
defaultness,
|
||||
|
|
@ -400,15 +403,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}))
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
|
||||
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
|
||||
let constness = attrs
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.find(|x| x.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |x| Const::Yes(x.span));
|
||||
let (generics, (safety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
constness,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -429,6 +427,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, bounds) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -609,30 +608,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// This is used to track which lifetimes have already been defined,
|
||||
// and which need to be replicated when lowering an async fn.
|
||||
|
||||
let generics = match parent_hir.node().expect_item().kind {
|
||||
let parent_item = parent_hir.node().expect_item();
|
||||
let constness = match parent_item.kind {
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
self.is_in_trait_impl = impl_.of_trait.is_some();
|
||||
&impl_.generics
|
||||
// N.B. the impl should always lower to methods that have `const host: bool` params if the trait
|
||||
// is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from
|
||||
// calling non-const impls are done through associated types.
|
||||
if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) {
|
||||
if let Some(local_def) = def_id.as_local() {
|
||||
match &self.ast_index[local_def] {
|
||||
AstOwner::Item(ast::Item { attrs, .. }) => attrs
|
||||
.iter()
|
||||
.find(|attr| attr.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||
_ => Const::No,
|
||||
}
|
||||
} else {
|
||||
self.tcx
|
||||
.get_attr(def_id, sym::const_trait)
|
||||
.map_or(Const::No, |attr| Const::Yes(attr.span))
|
||||
}
|
||||
} else {
|
||||
Const::No
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
|
||||
hir::ItemKind::Trait(_, _, _, _, _) => parent_hir
|
||||
.attrs
|
||||
.get(parent_item.hir_id().local_id)
|
||||
.iter()
|
||||
.find(|attr| attr.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||
kind => {
|
||||
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
||||
}
|
||||
};
|
||||
|
||||
if self.tcx.features().effects {
|
||||
self.host_param_id = generics
|
||||
.params
|
||||
.iter()
|
||||
.find(|param| {
|
||||
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
|
||||
})
|
||||
.map(|param| param.def_id);
|
||||
}
|
||||
|
||||
match ctxt {
|
||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
|
||||
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
|
||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
|
||||
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -648,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.lower_generics(generics, Const::No, i.id, itctx, |this| {
|
||||
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(
|
||||
|
|
@ -765,7 +779,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
fn lower_trait_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
trait_constness: Const,
|
||||
) -> &'hir hir::TraitItem<'hir> {
|
||||
let hir_id = self.lower_node_id(i.id);
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let trait_item_def_id = hir_id.expect_owner();
|
||||
|
|
@ -775,6 +793,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, kind) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -795,6 +814,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
trait_constness,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||
}
|
||||
|
|
@ -813,6 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
trait_constness,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
||||
}
|
||||
|
|
@ -822,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, kind) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -894,7 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.expr(span, hir::ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||
fn lower_impl_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
constness_of_trait: Const,
|
||||
) -> &'hir hir::ImplItem<'hir> {
|
||||
// Since `default impl` is not yet implemented, this is always true in impls.
|
||||
let has_value = true;
|
||||
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
||||
|
|
@ -905,6 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
|
|
@ -930,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||
sig.header.coroutine_kind,
|
||||
constness_of_trait,
|
||||
);
|
||||
|
||||
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
||||
|
|
@ -940,6 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
|
|
@ -1352,15 +1381,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
kind: FnDeclKind,
|
||||
coroutine_kind: Option<CoroutineKind>,
|
||||
parent_constness: Const,
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
||||
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
||||
let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No };
|
||||
let constness =
|
||||
if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||
});
|
||||
let (generics, decl) =
|
||||
self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
||||
|
|
@ -1436,6 +1468,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
generics: &Generics,
|
||||
constness: Const,
|
||||
force_append_constness: bool,
|
||||
parent_node_id: NodeId,
|
||||
itctx: ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
|
|
@ -1496,7 +1529,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// if the effects feature is enabled. This needs to be done before we lower where
|
||||
// clauses since where clauses need to bind to the DefId of the host param
|
||||
let host_param_parts = if let Const::Yes(span) = constness
|
||||
&& self.tcx.features().effects
|
||||
// if this comes from implementing a `const` trait, we must force constness to be appended
|
||||
// to the impl item, no matter whether effects is enabled.
|
||||
&& (self.tcx.features().effects || force_append_constness)
|
||||
{
|
||||
let span = self.lower_span(span);
|
||||
let param_node_id = self.next_node_id();
|
||||
|
|
@ -1609,6 +1644,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}),
|
||||
)),
|
||||
)),
|
||||
// FIXME(effects) we might not need a default.
|
||||
default: Some(self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const,
|
||||
hir_id: const_id,
|
||||
|
|
@ -1616,6 +1652,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
span,
|
||||
})),
|
||||
is_host_effect: true,
|
||||
synthetic: true,
|
||||
},
|
||||
colon_span: None,
|
||||
pure_wrt_drop: false,
|
||||
|
|
|
|||
|
|
@ -142,14 +142,19 @@ struct LoweringContext<'a, 'hir> {
|
|||
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
|
||||
|
||||
host_param_id: Option<LocalDefId>,
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
|
||||
fn new(
|
||||
tcx: TyCtxt<'hir>,
|
||||
resolver: &'a mut ResolverAstLowering,
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
// Pseudo-globals.
|
||||
tcx,
|
||||
resolver: resolver,
|
||||
resolver,
|
||||
arena: tcx.hir_arena,
|
||||
|
||||
// HirId handling.
|
||||
|
|
@ -185,6 +190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||
generics_def_id_map: Default::default(),
|
||||
host_param_id: None,
|
||||
ast_index,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2135,7 +2141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param: &GenericParam,
|
||||
source: hir::GenericParamSource,
|
||||
) -> hir::GenericParam<'hir> {
|
||||
let (name, kind) = self.lower_generic_param_kind(param, source);
|
||||
let (name, kind) = self.lower_generic_param_kind(
|
||||
param,
|
||||
source,
|
||||
attr::contains_name(¶m.attrs, sym::rustc_runtime),
|
||||
);
|
||||
|
||||
let hir_id = self.lower_node_id(param.id);
|
||||
self.lower_attrs(hir_id, ¶m.attrs);
|
||||
|
|
@ -2155,6 +2165,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&mut self,
|
||||
param: &GenericParam,
|
||||
source: hir::GenericParamSource,
|
||||
is_host_effect: bool,
|
||||
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
||||
match ¶m.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
|
|
@ -2220,7 +2231,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
(
|
||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
|
||||
hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2607,78 +2618,6 @@ struct GenericArgsCtor<'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> GenericArgsCtor<'hir> {
|
||||
fn push_constness(
|
||||
&mut self,
|
||||
lcx: &mut LoweringContext<'_, 'hir>,
|
||||
constness: ast::BoundConstness,
|
||||
) {
|
||||
if !lcx.tcx.features().effects {
|
||||
return;
|
||||
}
|
||||
|
||||
let (span, body) = match constness {
|
||||
BoundConstness::Never => return,
|
||||
BoundConstness::Always(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let body = hir::ExprKind::Lit(
|
||||
lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }),
|
||||
);
|
||||
|
||||
(span, body)
|
||||
}
|
||||
BoundConstness::Maybe(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let Some(host_param_id) = lcx.host_param_id else {
|
||||
lcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"no host param id for call in const yet no errors reported",
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let hir_id = lcx.next_id();
|
||||
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
||||
let body = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
lcx.arena.alloc(hir::Path {
|
||||
span,
|
||||
res,
|
||||
segments: arena_vec![
|
||||
lcx;
|
||||
hir::PathSegment::new(
|
||||
Ident { name: sym::host, span },
|
||||
hir_id,
|
||||
res
|
||||
)
|
||||
],
|
||||
}),
|
||||
));
|
||||
|
||||
(span, body)
|
||||
}
|
||||
};
|
||||
let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body)));
|
||||
|
||||
let id = lcx.next_node_id();
|
||||
let hir_id = lcx.next_id();
|
||||
|
||||
let def_id = lcx.create_def(
|
||||
lcx.current_hir_id_owner.def_id,
|
||||
id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
|
||||
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
self.args.push(hir::GenericArg::Const(hir::ConstArg {
|
||||
value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }),
|
||||
is_desugared_from_effects: true,
|
||||
}))
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.args.is_empty()
|
||||
&& self.constraints.is_empty()
|
||||
|
|
|
|||
|
|
@ -107,8 +107,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode,
|
||||
parenthesized_generic_args,
|
||||
itctx,
|
||||
// if this is the last segment, add constness to the trait path
|
||||
if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None },
|
||||
bound_modifier_allowed_features.clone(),
|
||||
)
|
||||
},
|
||||
|
|
@ -165,7 +163,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ParenthesizedGenericArgs::Err,
|
||||
itctx,
|
||||
None,
|
||||
None,
|
||||
));
|
||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||
|
||||
|
|
@ -208,7 +205,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(p.span),
|
||||
|
|
@ -222,7 +218,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext,
|
||||
constness: Option<ast::BoundConstness>,
|
||||
// Additional features ungated with a bound modifier like `async`.
|
||||
// This is passed down to the implicit associated type binding in
|
||||
// parenthesized bounds.
|
||||
|
|
@ -289,10 +284,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
)
|
||||
};
|
||||
|
||||
if let Some(constness) = constness {
|
||||
generic_args.push_constness(self, constness);
|
||||
}
|
||||
|
||||
let has_lifetimes =
|
||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
// Validate AST before lowering it to HIR.
|
||||
//
|
||||
// This pass is supposed to catch things that fit into AST data structures,
|
||||
// but not permitted by the language. It runs after expansion when AST is frozen,
|
||||
// so it can check for erroneous constructions produced by syntax extensions.
|
||||
// This pass is supposed to perform only simple checks not requiring name resolution
|
||||
// or type checking or some other kind of complex analysis.
|
||||
//! Validate AST before lowering it to HIR.
|
||||
//!
|
||||
//! This pass intends to check that the constructed AST is *syntactically valid* to allow the rest
|
||||
//! of the compiler to assume that the AST is valid. These checks cannot be performed during parsing
|
||||
//! because attribute macros are allowed to accept certain pieces of invalid syntax such as a
|
||||
//! function without body outside of a trait definition:
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! #[my_attribute]
|
||||
//! mod foo {
|
||||
//! fn missing_body();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! These checks are run post-expansion, after AST is frozen, to be able to check for erroneous
|
||||
//! constructions produced by proc macros. This pass is only intended for simple checks that do not
|
||||
//! require name resolution or type checking, or other kinds of complex analysis.
|
||||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_ast::ptr::P;
|
||||
|
|
@ -459,13 +469,18 @@ impl<'a> AstValidator<'a> {
|
|||
fn check_item_safety(&self, span: Span, safety: Safety) {
|
||||
match self.extern_mod_safety {
|
||||
Some(extern_safety) => {
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
|
||||
&& (extern_safety == Safety::Default || !self.features.unsafe_extern_blocks)
|
||||
{
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: self.current_extern_span().shrink_to_lo(),
|
||||
});
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) {
|
||||
if extern_safety == Safety::Default {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: Some(self.current_extern_span().shrink_to_lo()),
|
||||
});
|
||||
} else if !self.features.unsafe_extern_blocks {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
|
@ -1088,7 +1103,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
} else if let &Safety::Unsafe(span) = safety {
|
||||
this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
let mut diag = this
|
||||
.dcx()
|
||||
.create_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
&mut diag,
|
||||
self.session,
|
||||
sym::unsafe_extern_blocks,
|
||||
);
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
if abi.is_none() {
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ pub struct InvalidSafetyOnExtern {
|
|||
#[primary_span]
|
||||
pub item_span: Span,
|
||||
#[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")]
|
||||
pub block: Span,
|
||||
pub block: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use rustc_middle::span_bug;
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
|
||||
impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'infcx> {
|
||||
self.infcx.dcx()
|
||||
}
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
place: &str,
|
||||
borrow_place: &str,
|
||||
value_place: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
self.dcx().create_err(crate::session_diagnostics::MoveBorrow {
|
||||
place,
|
||||
span,
|
||||
|
|
@ -34,7 +34,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
desc: &str,
|
||||
borrow_span: Span,
|
||||
borrow_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -54,7 +54,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
old_loan_span: Span,
|
||||
old_opt_via: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
|
|
@ -101,7 +101,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
desc: &str,
|
||||
old_loan_span: Span,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
|
|
@ -134,7 +134,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
noun_old: &str,
|
||||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
|
|
@ -166,7 +166,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
second_borrow_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
|
|
@ -198,7 +198,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
kind_old: &str,
|
||||
msg_old: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
|
|
@ -239,7 +239,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
span: Span,
|
||||
borrow_span: Span,
|
||||
desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -256,12 +256,12 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
span: Span,
|
||||
desc: &str,
|
||||
is_arg: bool,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
|
||||
struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'tcx> {
|
||||
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0594, "cannot assign to {}", desc)
|
||||
}
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
move_from_span: Span,
|
||||
move_from_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
|
|
@ -287,7 +287,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
move_from_span: Span,
|
||||
ty: Ty<'_>,
|
||||
is_index: Option<bool>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let type_name = match (&ty.kind(), is_index) {
|
||||
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
|
||||
(&ty::Slice(_), _) => "slice",
|
||||
|
|
@ -308,7 +308,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
move_from_span: Span,
|
||||
container_ty: Ty<'_>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
|
|
@ -325,7 +325,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
verb: &str,
|
||||
optional_adverb_for_moved: &str,
|
||||
moved_path: Option<String>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
|
||||
|
||||
struct_span_code_err!(
|
||||
|
|
@ -344,7 +344,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
span: Span,
|
||||
path: &str,
|
||||
reason: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -362,7 +362,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
immutable_place: &str,
|
||||
immutable_section: &str,
|
||||
action: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
mutate_span,
|
||||
|
|
@ -380,7 +380,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
span: Span,
|
||||
yield_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
|
|
@ -391,7 +391,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
.with_span_label(yield_span, "possible yield occurs here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
borrow_span,
|
||||
|
|
@ -400,7 +400,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'tcx> {
|
||||
pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path,)
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
return_kind: &str,
|
||||
reference_desc: &str,
|
||||
path_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -433,7 +433,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
borrowed_path: &str,
|
||||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
closure_span,
|
||||
|
|
@ -445,7 +445,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
.with_span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"))
|
||||
}
|
||||
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -454,7 +454,7 @@ impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed",)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,24 +15,24 @@ use std::fmt;
|
|||
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
|
||||
|
||||
/// The results of the dataflow analyses used by the borrow checker.
|
||||
pub struct BorrowckResults<'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
pub struct BorrowckResults<'a, 'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>,
|
||||
}
|
||||
|
||||
/// The transient state of the dataflow analyses used by the borrow checker.
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckFlowState<'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub struct BorrowckFlowState<'a, 'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
|
||||
impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> {
|
||||
// All three analyses are forward, but we have to use just one here.
|
||||
type Direction = <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'mir, 'tcx>;
|
||||
type Direction = <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
BorrowckFlowState {
|
||||
|
|
@ -106,11 +106,11 @@ rustc_index::newtype_index! {
|
|||
/// `BorrowIndex`, and maps each such index to a `BorrowData`
|
||||
/// describing the borrow. These indexes are used for representing the
|
||||
/// borrows in compact bitvectors.
|
||||
pub struct Borrows<'mir, 'tcx> {
|
||||
pub struct Borrows<'a, 'mir, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
|
|
@ -389,12 +389,12 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
||||
impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
regioncx: &'mir RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
) -> Self {
|
||||
let mut borrows_out_of_scope_at_location =
|
||||
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);
|
||||
|
|
@ -494,7 +494,7 @@ impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
||||
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> {
|
||||
type Domain = BitSet<BorrowIndex>;
|
||||
|
||||
const NAME: &'static str = "borrows";
|
||||
|
|
@ -517,7 +517,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
|||
/// region stops containing the CFG points reachable from the issuing location.
|
||||
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
|
||||
/// `a.b.c` when `a` is overwritten.
|
||||
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> {
|
||||
type Idx = BorrowIndex;
|
||||
|
||||
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
|
|
@ -617,8 +617,8 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl DebugWithContext<Borrows<'_, '_>> for BorrowIndex {
|
||||
fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl DebugWithContext<Borrows<'_, '_, '_>> for BorrowIndex {
|
||||
fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", ctxt.location(*self))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,13 +149,13 @@ trait TypeOpInfo<'tcx> {
|
|||
|
||||
fn base_universe(&self) -> ty::UniverseIndex;
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>>;
|
||||
) -> Option<Diag<'infcx>>;
|
||||
|
||||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
|
|
@ -231,18 +231,25 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
|||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_prove_predicate_with_cause(&ocx, key, cause);
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,13 +275,13 @@ where
|
|||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
|
@ -288,7 +295,14 @@ where
|
|||
let (param_env, value) = key.into_parts();
|
||||
let _ = ocx.normalize(&cause, param_env, value.value);
|
||||
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,18 +322,25 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,13 +355,13 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||
self.base_universe.unwrap()
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
_cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
try_extract_error_from_region_constraints(
|
||||
mbcx.infcx,
|
||||
mbcx.mir_def_id(),
|
||||
|
|
@ -358,12 +379,12 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(skip(ocx), level = "debug")]
|
||||
fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
fn try_extract_error_from_fulfill_cx<'a, 'tcx>(
|
||||
ocx: &ObligationCtxt<'a, 'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'a>> {
|
||||
// We generally shouldn't have errors here because the query was
|
||||
// already run, but there's no point using `span_delayed_bug`
|
||||
// when we're going to emit an error here anyway.
|
||||
|
|
@ -381,15 +402,15 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
|
||||
fn try_extract_error_from_region_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
fn try_extract_error_from_region_constraints<'a, 'tcx>(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
|
||||
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'a>> {
|
||||
let placeholder_universe = match placeholder_region.kind() {
|
||||
ty::RePlaceholder(p) => p.universe,
|
||||
ty::ReVar(vid) => universe_of_region(vid),
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ enum StorageDeadOrDrop<'tcx> {
|
|||
Destructor(Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_use_of_moved_or_uninitialized(
|
||||
&mut self,
|
||||
location: Location,
|
||||
|
|
@ -341,7 +341,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
fn suggest_ref_or_clone(
|
||||
&self,
|
||||
mpi: MovePathIndex,
|
||||
err: &mut Diag<'tcx>,
|
||||
err: &mut Diag<'infcx>,
|
||||
in_pattern: &mut bool,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
) {
|
||||
|
|
@ -517,7 +517,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
desired_action: InitializationRequiringAction,
|
||||
span: Span,
|
||||
use_spans: UseSpans<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
// We need all statements in the body where the binding was assigned to later find all
|
||||
// the branching code paths where the binding *wasn't* assigned to.
|
||||
let inits = &self.move_data.init_path_map[mpi];
|
||||
|
|
@ -1288,7 +1288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let suggestion =
|
||||
let mut suggestion =
|
||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
format!(": {symbol}.clone()")
|
||||
} else {
|
||||
|
|
@ -1296,6 +1296,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
};
|
||||
let mut sugg = Vec::with_capacity(2);
|
||||
let mut inner_expr = expr;
|
||||
let mut is_raw_ptr = false;
|
||||
let typeck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
// Remove uses of `&` and `*` when suggesting `.clone()`.
|
||||
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
|
||||
&inner_expr.kind
|
||||
|
|
@ -1306,14 +1308,32 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
inner_expr = inner;
|
||||
if let Some(inner_type) = typeck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if inner_expr.span.lo() != expr.span.lo() {
|
||||
// Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863)
|
||||
if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr {
|
||||
// Remove "(*" or "(&"
|
||||
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
|
||||
}
|
||||
// Check whether `expr` is surrounded by parentheses or not.
|
||||
let span = if inner_expr.span.hi() != expr.span.hi() {
|
||||
// Account for `(*x)` to suggest `x.clone()`.
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
if is_raw_ptr {
|
||||
expr.span.shrink_to_hi()
|
||||
} else {
|
||||
// Remove the close parenthesis ")"
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
}
|
||||
} else {
|
||||
if is_raw_ptr {
|
||||
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||
suggestion = ").clone()".to_string();
|
||||
}
|
||||
expr.span.shrink_to_hi()
|
||||
};
|
||||
sugg.push((span, suggestion));
|
||||
|
|
@ -1441,7 +1461,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
location: Location,
|
||||
(place, _span): (Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
||||
let borrow_span = borrow_spans.args_or_use();
|
||||
|
||||
|
|
@ -1491,7 +1511,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
(place, span): (Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
issued_borrow: &BorrowData<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
|
||||
let issued_span = issued_spans.args_or_use();
|
||||
|
||||
|
|
@ -1782,7 +1802,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
err
|
||||
}
|
||||
|
||||
fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'tcx>, place: Place<'tcx>) {
|
||||
fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'infcx>, place: Place<'tcx>) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
|
||||
|
|
@ -2841,7 +2861,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
drop_span: Span,
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
debug!(
|
||||
"report_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}, {:?}\
|
||||
|
|
@ -3016,7 +3036,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
drop_span: Span,
|
||||
borrow_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
debug!(
|
||||
"report_thread_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}\
|
||||
|
|
@ -3041,7 +3061,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
borrow_spans: UseSpans<'tcx>,
|
||||
proper_span: Span,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||
explanation
|
||||
{
|
||||
|
|
@ -3206,7 +3226,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
return_span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
opt_place_desc: Option<&String>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'infcx>> {
|
||||
let return_kind = match category {
|
||||
ConstraintCategory::Return(_) => "return",
|
||||
ConstraintCategory::Yield => "yield",
|
||||
|
|
@ -3299,7 +3319,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
constraint_span: Span,
|
||||
captured_var: &str,
|
||||
scope: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let args_span = use_span.args_or_use();
|
||||
|
||||
|
|
@ -3411,7 +3431,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
upvar_span: Span,
|
||||
upvar_name: Symbol,
|
||||
escape_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ pub(super) struct DescribePlaceOpt {
|
|||
|
||||
pub(super) struct IncludingTupleField(pub(super) bool);
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
|
||||
/// is moved after being invoked.
|
||||
///
|
||||
|
|
@ -86,7 +86,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
location: Location,
|
||||
place: PlaceRef<'tcx>,
|
||||
diag: &mut Diag<'_>,
|
||||
diag: &mut Diag<'infcx>,
|
||||
) -> bool {
|
||||
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
|
||||
let mut target = place.local_or_deref_local();
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_move_errors(&mut self) {
|
||||
let grouped_errors = self.group_move_errors();
|
||||
for error in grouped_errors {
|
||||
|
|
@ -291,7 +291,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'tcx> {
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
let description = if place.projection.len() == 1 {
|
||||
format!("static item {}", self.describe_any_place(place.as_ref()))
|
||||
} else {
|
||||
|
|
@ -428,7 +428,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
deref_target_place: Place<'tcx>,
|
||||
span: Span,
|
||||
use_spans: Option<UseSpans<'tcx>>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
// Inspect the type of the content behind the
|
||||
// borrow to provide feedback about why this
|
||||
|
|
@ -639,12 +639,27 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
||||
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
||||
Ok(snippet) if snippet.starts_with('*') => {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let sp = span.with_lo(span.lo() + BytePos(1));
|
||||
let inner = self.find_expr(sp);
|
||||
let mut is_raw_ptr = false;
|
||||
if let Some(inner) = inner {
|
||||
let typck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
if let Some(inner_type) = typck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the `inner` is a raw pointer, do not suggest removing the "*", see #126863
|
||||
// FIXME: need to check whether the assigned object can be a raw pointer, see `tests/ui/borrowck/issue-20801.rs`.
|
||||
if !is_raw_ptr {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
err.span_suggestion_verbose(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub(crate) enum AccessKind {
|
|||
Mutate,
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_mutability_error(
|
||||
&mut self,
|
||||
access_place: Place<'tcx>,
|
||||
|
|
@ -541,7 +541,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
}
|
||||
|
||||
/// Suggest `map[k] = v` => `map.insert(k, v)` and the like.
|
||||
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) {
|
||||
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'infcx>, span: Span) {
|
||||
let Some(adt) = ty.ty_adt_def() else { return };
|
||||
let did = adt.did();
|
||||
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|
||||
|
|
@ -550,13 +550,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
/// Walks through the HIR, looking for the corresponding span for this error.
|
||||
/// When it finds it, see if it corresponds to assignment operator whose LHS
|
||||
/// is an index expr.
|
||||
struct SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||
struct SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> {
|
||||
assign_span: Span,
|
||||
err: &'a mut Diag<'tcx>,
|
||||
err: &'a mut Diag<'infcx>,
|
||||
ty: Ty<'tcx>,
|
||||
suggested: bool,
|
||||
}
|
||||
impl<'a, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||
impl<'a, 'cx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'cx, 'tcx> {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||
hir::intravisit::walk_stmt(self, stmt);
|
||||
let expr = match stmt.kind {
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ pub struct ErrorConstraintInfo<'tcx> {
|
|||
pub(super) span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
/// Converts a region inference variable into a `ty::Region` that
|
||||
/// we can use for error reporting. If `r` is universally bound,
|
||||
/// then we use the name that we have on record for it. If `r` is
|
||||
|
|
@ -360,7 +360,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
let diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
self.infcx,
|
||||
self.mir_def_id(),
|
||||
span,
|
||||
named_ty,
|
||||
|
|
@ -589,7 +589,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
kind: ReturnConstraint,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||
|
||||
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
|
|
@ -658,7 +658,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
/// | ^^^^^^^^^^ `x` escapes the function body here
|
||||
/// ```
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
|
||||
fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||
|
||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
|
|
@ -767,7 +767,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo {
|
||||
fr,
|
||||
fr_is_local,
|
||||
|
|
|
|||
|
|
@ -310,8 +310,8 @@ fn do_mir_borrowck<'tcx>(
|
|||
promoted_mbcx.report_move_errors();
|
||||
diags = promoted_mbcx.diags;
|
||||
|
||||
struct MoveVisitor<'a, 'b, 'mir, 'cx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'cx, 'tcx>,
|
||||
struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
|
||||
|
|
@ -528,8 +528,8 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> {
|
||||
infcx: &'cx BorrowckInferCtxt<'tcx>,
|
||||
struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
|
|
@ -596,7 +596,7 @@ struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> {
|
|||
/// Results of Polonius analysis.
|
||||
polonius_output: Option<Rc<PoloniusOutput>>,
|
||||
|
||||
diags: diags::BorrowckDiags<'tcx>,
|
||||
diags: diags::BorrowckDiags<'infcx, 'tcx>,
|
||||
move_errors: Vec<MoveError<'tcx>>,
|
||||
}
|
||||
|
||||
|
|
@ -605,15 +605,15 @@ struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> {
|
|||
// 2. loans made in overlapping scopes do not conflict
|
||||
// 3. assignments do not affect things loaned out as immutable
|
||||
// 4. moves do not affect things loaned out in any way
|
||||
impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
||||
for MirBorrowckCtxt<'_, 'mir, '_, 'tcx>
|
||||
impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
||||
for MirBorrowckCtxt<'a, 'mir, '_, 'tcx>
|
||||
{
|
||||
type FlowState = Flows<'mir, 'tcx>;
|
||||
type FlowState = Flows<'a, 'mir, 'tcx>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
stmt: &'mir Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
|
|
@ -683,7 +683,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
|||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
|
|
@ -794,7 +794,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
|||
fn visit_terminator_after_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
|
|
@ -988,7 +988,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
place_span: (Place<'tcx>, Span),
|
||||
kind: (AccessDepth, ReadOrWrite),
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let (sd, rw) = kind;
|
||||
|
||||
|
|
@ -1038,7 +1038,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
place_span: (Place<'tcx>, Span),
|
||||
sd: AccessDepth,
|
||||
rw: ReadOrWrite,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) -> bool {
|
||||
let mut error_reported = false;
|
||||
let borrow_set = Rc::clone(&self.borrow_set);
|
||||
|
|
@ -1179,7 +1179,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
location: Location,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
kind: AccessDepth,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// Write of P[i] or *P requires P init'd.
|
||||
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
|
||||
|
|
@ -1197,7 +1197,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
&mut self,
|
||||
location: Location,
|
||||
(rvalue, span): (&'mir Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
|
|
@ -1455,7 +1455,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
&mut self,
|
||||
location: Location,
|
||||
(operand, span): (&'mir Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
match *operand {
|
||||
Operand::Copy(place) => {
|
||||
|
|
@ -1579,7 +1579,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
&mut self,
|
||||
location: Location,
|
||||
span: Span,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// Two-phase borrow support: For each activation that is newly
|
||||
// generated at this statement, check if it interferes with
|
||||
|
|
@ -1743,7 +1743,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
|
|
@ -1848,7 +1848,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
|
|
@ -1947,7 +1947,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
&mut self,
|
||||
location: Location,
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
debug!("check_if_assigned_path_is_moved place: {:?}", place);
|
||||
|
||||
|
|
@ -2013,7 +2013,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
location: Location,
|
||||
base: PlaceRef<'tcx>,
|
||||
span: Span,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// rust-lang/rust#21232: Until Rust allows reads from the
|
||||
// initialized parts of partially initialized structs, we
|
||||
|
|
@ -2104,7 +2104,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
(place, span): (Place<'tcx>, Span),
|
||||
kind: ReadOrWrite,
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
debug!(
|
||||
|
|
@ -2220,7 +2220,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
fn is_local_ever_initialized(
|
||||
&self,
|
||||
local: Local,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) -> Option<InitIndex> {
|
||||
let mpi = self.move_data.rev_lookup.find_local(local)?;
|
||||
let ii = &self.move_data.init_path_map[mpi];
|
||||
|
|
@ -2228,7 +2228,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'mir, 'tcx>) {
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) {
|
||||
match root_place {
|
||||
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
|
||||
// If the local may have been initialized, and it is now currently being
|
||||
|
|
@ -2428,12 +2428,12 @@ mod diags {
|
|||
|
||||
use super::*;
|
||||
|
||||
enum BufferedDiag<'tcx> {
|
||||
Error(Diag<'tcx>),
|
||||
NonError(Diag<'tcx, ()>),
|
||||
enum BufferedDiag<'infcx> {
|
||||
Error(Diag<'infcx>),
|
||||
NonError(Diag<'infcx, ()>),
|
||||
}
|
||||
|
||||
impl<'tcx> BufferedDiag<'tcx> {
|
||||
impl<'infcx> BufferedDiag<'infcx> {
|
||||
fn sort_span(&self) -> Span {
|
||||
match self {
|
||||
BufferedDiag::Error(diag) => diag.sort_span,
|
||||
|
|
@ -2442,7 +2442,7 @@ mod diags {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct BorrowckDiags<'tcx> {
|
||||
pub struct BorrowckDiags<'infcx, 'tcx> {
|
||||
/// This field keeps track of move errors that are to be reported for given move indices.
|
||||
///
|
||||
/// There are situations where many errors can be reported for a single move out (see
|
||||
|
|
@ -2457,15 +2457,15 @@ mod diags {
|
|||
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
|
||||
/// when errors in the map are being re-added to the error buffer so that errors with the
|
||||
/// same primary span come out in a consistent order.
|
||||
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'tcx>)>,
|
||||
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>,
|
||||
|
||||
buffered_mut_errors: FxIndexMap<Span, (Diag<'tcx>, usize)>,
|
||||
buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>,
|
||||
|
||||
/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
|
||||
buffered_diags: Vec<BufferedDiag<'tcx>>,
|
||||
buffered_diags: Vec<BufferedDiag<'infcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> BorrowckDiags<'tcx> {
|
||||
impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> {
|
||||
pub fn new() -> Self {
|
||||
BorrowckDiags {
|
||||
buffered_move_errors: BTreeMap::new(),
|
||||
|
|
@ -2474,28 +2474,28 @@ mod diags {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'infcx>) {
|
||||
self.buffered_diags.push(BufferedDiag::Error(diag));
|
||||
}
|
||||
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) {
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
|
||||
self.buffered_diags.push(BufferedDiag::NonError(diag));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'infcx>) {
|
||||
self.diags.buffer_error(diag);
|
||||
}
|
||||
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) {
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
|
||||
self.diags.buffer_non_error(diag);
|
||||
}
|
||||
|
||||
pub fn buffer_move_error(
|
||||
&mut self,
|
||||
move_out_indices: Vec<MoveOutIndex>,
|
||||
place_and_err: (PlaceRef<'tcx>, Diag<'tcx>),
|
||||
place_and_err: (PlaceRef<'tcx>, Diag<'infcx>),
|
||||
) -> bool {
|
||||
if let Some((_, diag)) =
|
||||
self.diags.buffered_move_errors.insert(move_out_indices, place_and_err)
|
||||
|
|
@ -2508,12 +2508,12 @@ mod diags {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'tcx>, usize)> {
|
||||
pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> {
|
||||
// FIXME(#120456) - is `swap_remove` correct?
|
||||
self.diags.buffered_mut_errors.swap_remove(&span)
|
||||
}
|
||||
|
||||
pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'tcx>, count: usize) {
|
||||
pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) {
|
||||
self.diags.buffered_mut_errors.insert(span, (diag, count));
|
||||
}
|
||||
|
||||
|
|
@ -2554,7 +2554,7 @@ mod diags {
|
|||
pub fn has_move_error(
|
||||
&self,
|
||||
move_out_indices: &[MoveOutIndex],
|
||||
) -> Option<&(PlaceRef<'tcx>, Diag<'tcx>)> {
|
||||
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
|
||||
self.diags.buffered_move_errors.get(move_out_indices)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
location_table: &LocationTable,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
|
|
@ -262,13 +262,13 @@ pub(super) fn dump_mir_results<'tcx>(
|
|||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(super) fn dump_annotation<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
pub(super) fn dump_annotation<'tcx, 'cx>(
|
||||
infcx: &'cx BorrowckInferCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
||||
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
||||
diags: &mut crate::diags::BorrowckDiags<'tcx>,
|
||||
diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>,
|
||||
) {
|
||||
let tcx = infcx.tcx;
|
||||
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
|
||||
|
|
@ -285,7 +285,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||
|
||||
let def_span = tcx.def_span(body.source.def_id());
|
||||
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
||||
let mut err = tcx.dcx().struct_span_note(def_span, "external requirements");
|
||||
let mut err = infcx.dcx().struct_span_note(def_span, "external requirements");
|
||||
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||
|
||||
err
|
||||
} else {
|
||||
let mut err = tcx.dcx().struct_span_note(def_span, "no external requirements");
|
||||
let mut err = infcx.dcx().struct_span_note(def_span, "no external requirements");
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
if let Err(guar) =
|
||||
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
|
||||
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
|
||||
{
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
|
|
@ -294,6 +294,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
|
||||
.ty;
|
||||
|
||||
if let Err(e) = definition_ty.error_reported() {
|
||||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
// `definition_ty` does not live in of the current inference context,
|
||||
// so lets make sure that we don't accidentally misuse our current `infcx`.
|
||||
match check_opaque_type_well_formed(
|
||||
|
|
@ -387,10 +391,11 @@ fn check_opaque_type_well_formed<'tcx>(
|
|||
/// [rustc-dev-guide chapter]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||
fn check_opaque_type_parameter_valid<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = infcx.tcx;
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
|
||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||
|
|
@ -420,7 +425,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
|
|||
|
||||
opaque_env.param_is_error(i)?;
|
||||
|
||||
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||
ty: arg,
|
||||
kind,
|
||||
span,
|
||||
|
|
@ -438,7 +443,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
|
|||
.collect();
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
return Err(tcx
|
||||
return Err(infcx
|
||||
.dcx()
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.with_span_note(spans, format!("{descr} used multiple times"))
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub(super) fn generate<'mir, 'tcx>(
|
|||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
) {
|
||||
debug!("liveness::generate");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
relevant_live_locals: Vec<Local>,
|
||||
boring_locals: Vec<Local>,
|
||||
|
|
@ -101,7 +101,7 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
}
|
||||
|
||||
/// Contextual state for the type-liveness coroutine.
|
||||
struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
||||
struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
/// Current type-checker, giving us our inference context etc.
|
||||
typeck: &'me mut TypeChecker<'typeck, 'tcx>,
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
|||
|
||||
/// Results of dataflow tracking which variables (and paths) have been
|
||||
/// initialized.
|
||||
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,
|
||||
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>,
|
||||
|
||||
/// Index indicating where each variable is assigned, used, or
|
||||
/// dropped.
|
||||
|
|
@ -131,8 +131,8 @@ struct DropData<'tcx> {
|
|||
region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>,
|
||||
}
|
||||
|
||||
struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>,
|
||||
struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>,
|
||||
|
||||
/// Set of points that define the current local.
|
||||
defs: BitSet<PointIndex>,
|
||||
|
|
@ -153,8 +153,8 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||
stack: Vec<PointIndex>,
|
||||
}
|
||||
|
||||
impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self {
|
||||
impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self {
|
||||
let num_points = cx.elements.num_points();
|
||||
LivenessResults {
|
||||
cx,
|
||||
|
|
@ -507,7 +507,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> {
|
||||
/// Returns `true` if the local variable (or some part of it) is initialized at the current
|
||||
/// cursor position. Callers should call one of the `seek` methods immediately before to point
|
||||
/// the cursor to the desired location.
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
|
||||
/// MIR visitor for collecting used mutable variables.
|
||||
/// The 'visit lifetime represents the duration of the MIR walk.
|
||||
struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'cx, 'tcx> {
|
||||
struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> {
|
||||
temporary_used_locals: FxIndexSet<Local>,
|
||||
never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
|
||||
|
|
|
|||
|
|
@ -55,10 +55,6 @@ jobs:
|
|||
if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
|
||||
run: rustup set default-host x86_64-apple-darwin
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ jobs:
|
|||
env:
|
||||
TARGET_TRIPLE: aarch64-unknown-linux-gnu
|
||||
apt_deps: gcc-aarch64-linux-gnu qemu-user
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-apple-darwin
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
TARGET_TRIPLE: s390x-unknown-linux-gnu
|
||||
|
|
@ -108,10 +111,6 @@ jobs:
|
|||
sudo apt-get update
|
||||
sudo apt-get install -y ${{ matrix.apt_deps }}
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
|
|
@ -214,6 +213,9 @@ jobs:
|
|||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-apple-darwin
|
||||
# cross-compile from Linux to Windows using mingw
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
|
|
@ -248,10 +250,6 @@ jobs:
|
|||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-mingw-w64-x86-64
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
|
|
@ -282,7 +280,8 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
needs: [rustfmt, test, bench, dist]
|
||||
# FIXME add the bench job back to the dependency list once rust-lang/rust#125493 gets merged
|
||||
needs: [rustfmt, test, dist]
|
||||
|
||||
permissions:
|
||||
contents: write # for creating the dev tag and release
|
||||
|
|
|
|||
|
|
@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b27922a6879b5b5361d0a084cb0b1941bf109a98540addcb932da13b68bed4"
|
||||
checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "304c455b28bf56372729acb356afbb55d622f2b0f2f7837aa5e57c138acaac4d"
|
||||
checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
|
|
@ -70,45 +70,46 @@ dependencies = [
|
|||
"hashbrown 0.14.3",
|
||||
"log",
|
||||
"regalloc2",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1653c56b99591d07f67c5ca7f9f25888948af3f4b97186bff838d687d666f613"
|
||||
checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5b6a9cf6b6eb820ee3f973a0db313c05dc12d370f37b4fe9630286e1672573f"
|
||||
checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9d06e6bf30075fb6bed9e034ec046475093392eea1aff90eb5c44c4a033d19a"
|
||||
checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29be04f931b73cdb9694874a295027471817f26f26d2f0ebe5454153176b6e3a"
|
||||
checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a07fd7393041d7faa2f37426f5dc7fc04003b70988810e8c063beefeff1cd8f9"
|
||||
checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
|
|
@ -118,15 +119,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f341d7938caa6dff8149dac05bb2b53fc680323826b83b4cf175ab9f5139a3c9"
|
||||
checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42733555e06433f1461570e09dbd756dafc228b4dac75c597cdbdc518de07522"
|
||||
checksum = "f5c5cfb8bbd3339cd25cca30e7516ff8fe5cb1feeddde6980cc4d5ef34df97bb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -144,9 +145,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84950af02bb85f3da764d53a953b43bb29a732e793d4fe24637a61591be9a024"
|
||||
checksum = "7c9b0d4269b36fd858e6d8f20cd4938941186fb831488c361888cb2d6b33a9a6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -155,9 +156,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82af6066e6448d26eeabb7aa26a43f7ff79f8217b06bade4ee6ef230aecc8880"
|
||||
checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
|
|
@ -166,9 +167,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00af56107039ed150391df6f753298c7b08f2b6a2e0727d216b5fa599d684d8b"
|
||||
checksum = "19e33439ec20db058bc7cc3410f9748ab1ad90a35cef713d625c736f43e3820d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -278,9 +279,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.33.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
|
||||
checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown 0.14.3",
|
||||
|
|
@ -410,10 +411,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "20.0.0"
|
||||
version = "22.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a9f93a3289057b26dc75eb84d6e60d7694f7d169c7c09597495de6e016a13ff"
|
||||
checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ crate-type = ["dylib"]
|
|||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.107.0", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.107.0" }
|
||||
cranelift-module = { version = "0.107.0" }
|
||||
cranelift-native = { version = "0.107.0" }
|
||||
cranelift-jit = { version = "0.107.0", optional = true }
|
||||
cranelift-object = { version = "0.107.0" }
|
||||
cranelift-codegen = { version = "0.109.0", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.109.0" }
|
||||
cranelift-module = { version = "0.109.0" }
|
||||
cranelift-native = { version = "0.109.0" }
|
||||
cranelift-jit = { version = "0.109.0", optional = true }
|
||||
cranelift-object = { version = "0.109.0" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.28", default-features = false, features = ["write"]}
|
||||
object = { version = "0.33", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "2.0.0"
|
||||
libloading = { version = "0.8.0", optional = true }
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
|||
|FreeBSD|✅[^no-rustup]|❓|❓|❓|
|
||||
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|
||||
|Other unixes|❓|❓|❓|❓|
|
||||
|macOS|✅|❌[^apple-silicon]|N/A|N/A|
|
||||
|macOS|✅|✅[^no-rustup]|N/A|N/A|
|
||||
|Windows|✅[^no-rustup]|❌|N/A|N/A|
|
||||
|
||||
✅: Fully supported and tested
|
||||
|
|
@ -80,7 +80,6 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
|||
Not all targets are available as rustup component for nightly. See notes in the platform support matrix.
|
||||
|
||||
[^xcoff]: XCOFF object file format is not supported.
|
||||
[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248).
|
||||
[^no-rustup]: Not available as rustup component for nightly. You can build it yourself.
|
||||
|
||||
## Usage
|
||||
|
|
|
|||
|
|
@ -267,10 +267,6 @@ fn build_clif_sysroot_for_triple(
|
|||
prefix.to_str().unwrap()
|
||||
));
|
||||
}
|
||||
rustflags.push("-Zunstable-options".to_owned());
|
||||
for (name, values) in EXTRA_CHECK_CFGS {
|
||||
rustflags.push(check_cfg_arg(name, *values));
|
||||
}
|
||||
compiler.rustflags.extend(rustflags);
|
||||
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
|
||||
if channel == "release" {
|
||||
|
|
@ -330,34 +326,3 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
|
|||
|
||||
Some(target_libs)
|
||||
}
|
||||
|
||||
// Copied from https://github.com/rust-lang/rust/blob/4fd98a4b1b100f5329c6efae18031791f64372d2/src/bootstrap/src/utils/helpers.rs#L569-L585
|
||||
/// Create a `--check-cfg` argument invocation for a given name
|
||||
/// and it's values.
|
||||
fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
|
||||
// Creating a string of the values by concatenating each value:
|
||||
// ',values("tvos","watchos")' or '' (nothing) when there are no values.
|
||||
let next = match values {
|
||||
Some(values) => {
|
||||
let mut tmp = values.iter().flat_map(|val| [",", "\"", val, "\""]).collect::<String>();
|
||||
|
||||
tmp.insert_str(1, "values(");
|
||||
tmp.push(')');
|
||||
tmp
|
||||
}
|
||||
None => "".to_string(),
|
||||
};
|
||||
format!("--check-cfg=cfg({name}{next})")
|
||||
}
|
||||
|
||||
const EXTRA_CHECK_CFGS: &[(&str, Option<&[&str]>)] = &[
|
||||
("bootstrap", None),
|
||||
("stdarch_intel_sde", None),
|
||||
("no_fp_fmt_parse", None),
|
||||
("no_global_oom_handling", None),
|
||||
("no_rc", None),
|
||||
("no_sync", None),
|
||||
("netbsd10", None),
|
||||
("backtrace_in_libstd", None),
|
||||
("target_arch", Some(&["xtensa"])),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -329,7 +329,6 @@ pub(crate) fn run_tests(
|
|||
struct TestRunner<'a> {
|
||||
is_native: bool,
|
||||
jit_supported: bool,
|
||||
use_unstable_features: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
dirs: Dirs,
|
||||
target_compiler: Compiler,
|
||||
|
|
@ -361,15 +360,7 @@ impl<'a> TestRunner<'a> {
|
|||
&& target_compiler.triple.contains("x86_64")
|
||||
&& !target_compiler.triple.contains("windows");
|
||||
|
||||
Self {
|
||||
is_native,
|
||||
jit_supported,
|
||||
use_unstable_features,
|
||||
skip_tests,
|
||||
dirs,
|
||||
target_compiler,
|
||||
stdlib_source,
|
||||
}
|
||||
Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
|
||||
}
|
||||
|
||||
fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
|
|
@ -393,31 +384,13 @@ impl<'a> TestRunner<'a> {
|
|||
match *cmd {
|
||||
TestCaseCmd::Custom { func } => func(self),
|
||||
TestCaseCmd::BuildLib { source, crate_types } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
} else {
|
||||
self.run_rustc([
|
||||
source,
|
||||
"--crate-type",
|
||||
crate_types,
|
||||
"--cfg",
|
||||
"no_unstable_features",
|
||||
]);
|
||||
}
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
}
|
||||
TestCaseCmd::BuildBin { source } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source]);
|
||||
} else {
|
||||
self.run_rustc([source, "--cfg", "no_unstable_features"]);
|
||||
}
|
||||
self.run_rustc([source]);
|
||||
}
|
||||
TestCaseCmd::BuildBinAndRun { source, args } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source]);
|
||||
} else {
|
||||
self.run_rustc([source, "--cfg", "no_unstable_features"]);
|
||||
}
|
||||
self.run_rustc([source]);
|
||||
self.run_out_command(
|
||||
source.split('/').last().unwrap().split('.').next().unwrap(),
|
||||
args,
|
||||
|
|
@ -472,7 +445,6 @@ impl<'a> TestRunner<'a> {
|
|||
cmd.arg(&self.target_compiler.triple);
|
||||
cmd.arg("-Cpanic=abort");
|
||||
cmd.arg("-Zunstable-options");
|
||||
cmd.arg("--check-cfg=cfg(no_unstable_features)");
|
||||
cmd.arg("--check-cfg=cfg(jit)");
|
||||
cmd.args(args);
|
||||
cmd
|
||||
|
|
|
|||
|
|
@ -333,12 +333,7 @@ fn main() {
|
|||
#[cfg(all(not(jit), not(all(windows, target_env = "gnu"))))]
|
||||
test_tls();
|
||||
|
||||
#[cfg(all(
|
||||
not(jit),
|
||||
not(no_unstable_features),
|
||||
target_arch = "x86_64",
|
||||
any(target_os = "linux", target_os = "macos")
|
||||
))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
|
||||
unsafe {
|
||||
global_asm_test();
|
||||
naked_test();
|
||||
|
|
@ -367,17 +362,12 @@ fn stack_val_align() {
|
|||
assert_eq!(&a as *const Foo as usize % 8192, 0);
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(jit),
|
||||
not(no_unstable_features),
|
||||
target_arch = "x86_64",
|
||||
any(target_os = "linux", target_os = "macos")
|
||||
))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
|
||||
extern "C" {
|
||||
fn global_asm_test();
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "linux"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
|
||||
global_asm! {
|
||||
"
|
||||
.global global_asm_test
|
||||
|
|
@ -387,7 +377,7 @@ global_asm! {
|
|||
"
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "macos"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", target_os = "macos"))]
|
||||
global_asm! {
|
||||
"
|
||||
.global _global_asm_test
|
||||
|
|
@ -397,7 +387,7 @@ global_asm! {
|
|||
"
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64"))]
|
||||
#[naked]
|
||||
extern "C" fn naked_test() {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -251,6 +251,9 @@ unsafe fn test_simd() {
|
|||
test_mm_add_epi8();
|
||||
test_mm_add_pd();
|
||||
test_mm_cvtepi8_epi16();
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cvtps_epi32();
|
||||
test_mm_cvttps_epi32();
|
||||
test_mm_cvtsi128_si64();
|
||||
|
||||
test_mm_extract_epi8();
|
||||
|
|
@ -476,6 +479,41 @@ unsafe fn test_mm256_permutevar8x32_epi32() {
|
|||
assert_eq_m256i(r, e);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
#[cfg(not(jit))]
|
||||
unsafe fn test_mm_cvtps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvtps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn test_mm_cvttps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvttps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
|
||||
fn test_checked_mul() {
|
||||
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||
assert_eq!(u, None);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.21.0"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"gimli 0.29.0",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -133,6 +133,17 @@ dependencies = [
|
|||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
|
|
@ -147,9 +158,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
|
|
@ -189,9 +200,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
|
|
@ -286,9 +297,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -396,8 +407,6 @@ dependencies = [
|
|||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"std",
|
||||
]
|
||||
|
||||
|
|
@ -430,7 +439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"gimli 0.28.1",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-05-13"
|
||||
channel = "nightly-2024-06-30"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
|
|
|
|||
|
|
@ -36,9 +36,8 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
|
|||
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
|
||||
|
||||
# exotic linkages
|
||||
rm tests/ui/issues/issue-33992.rs # unsupported linkages
|
||||
rm tests/incremental/hashes/function_interfaces.rs # same
|
||||
rm tests/incremental/hashes/statics.rs # same
|
||||
rm tests/incremental/hashes/function_interfaces.rs
|
||||
rm tests/incremental/hashes/statics.rs
|
||||
|
||||
# variadic arguments
|
||||
rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
|
||||
|
|
@ -60,13 +59,20 @@ rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
|
|||
|
||||
# requires LTO
|
||||
rm -r tests/run-make/cdylib
|
||||
rm -r tests/run-make/issue-14500
|
||||
rm -r tests/run-make/issue-64153
|
||||
rm -r tests/run-make/codegen-options-parsing
|
||||
rm -r tests/run-make/lto-*
|
||||
rm -r tests/run-make/reproducible-build-2
|
||||
rm -r tests/run-make/issue-109934-lto-debuginfo
|
||||
rm -r tests/run-make/no-builtins-lto
|
||||
rm -r tests/run-make/reachable-extern-fn-available-lto
|
||||
|
||||
# coverage instrumentation
|
||||
rm tests/ui/consts/precise-drop-with-coverage.rs
|
||||
rm tests/ui/issues/issue-85461.rs
|
||||
rm -r tests/ui/instrument-coverage/
|
||||
|
||||
# missing f16/f128 support
|
||||
rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
|
||||
|
||||
# optimization tests
|
||||
# ==================
|
||||
|
|
@ -74,6 +80,7 @@ rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations
|
|||
rm tests/ui/codegen/init-large-type.rs # same
|
||||
rm tests/ui/issues/issue-40883.rs # same
|
||||
rm -r tests/run-make/fmt-write-bloat/ # tests an optimization
|
||||
rm tests/ui/statics/const_generics.rs # same
|
||||
|
||||
# backend specific tests
|
||||
# ======================
|
||||
|
|
@ -85,6 +92,7 @@ rm -r tests/run-make/sepcomp-cci-copies # same
|
|||
rm -r tests/run-make/volatile-intrinsics # same
|
||||
rm -r tests/run-make/llvm-ident # same
|
||||
rm -r tests/run-make/no-builtins-attribute # same
|
||||
rm -r tests/run-make/pgo-gen-no-imp-symbols # same
|
||||
rm tests/ui/abi/stack-protector.rs # requires stack protector support
|
||||
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
|
||||
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
|
||||
|
|
@ -93,13 +101,14 @@ rm -r tests/run-make/print-to-output # requires --print relocation-models
|
|||
# requires asm, llvm-ir and/or llvm-bc emit support
|
||||
# =============================================
|
||||
rm -r tests/run-make/emit-named-files
|
||||
rm -r tests/run-make/issue-30063
|
||||
rm -r tests/run-make/multiple-emits
|
||||
rm -r tests/run-make/output-type-permutations
|
||||
rm -r tests/run-make/emit-to-stdout
|
||||
rm -r tests/run-make/compressed-debuginfo
|
||||
rm -r tests/run-make/symbols-include-type-name
|
||||
|
||||
rm -r tests/run-make/notify-all-emit-artifacts
|
||||
rm -r tests/run-make/reset-codegen-1
|
||||
rm -r tests/run-make/inline-always-many-cgu
|
||||
|
||||
# giving different but possibly correct results
|
||||
# =============================================
|
||||
|
|
@ -118,6 +127,7 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain
|
|||
# ============
|
||||
rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
|
||||
rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
|
||||
rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold
|
||||
|
||||
# bugs in the test suite
|
||||
# ======================
|
||||
|
|
@ -148,12 +158,12 @@ index 9607ff02f96..b7d97caf9a2 100644
|
|||
--- a/src/tools/run-make-support/src/rustdoc.rs
|
||||
+++ b/src/tools/run-make-support/src/rustdoc.rs
|
||||
@@ -34,8 +34,6 @@ pub fn bare() -> Self {
|
||||
/// Construct a \`rustdoc\` invocation with \`-L \$(TARGET_RPATH_DIR)\` set.
|
||||
#[track_caller]
|
||||
pub fn new() -> Self {
|
||||
let mut cmd = setup_common();
|
||||
- let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
|
||||
- let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
|
||||
- cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ mod pass_mode;
|
|||
mod returning;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
||||
use cranelift_codegen::ir::SigRef;
|
||||
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
|
||||
|
|
@ -17,7 +18,7 @@ use rustc_middle::ty::TypeVisitableExt;
|
|||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::call::{Conv, FnAbi};
|
||||
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use self::pass_mode::*;
|
||||
|
|
@ -487,6 +488,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
let args = args;
|
||||
assert_eq!(fn_abi.args.len(), args.len());
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CallTarget {
|
||||
Direct(FuncRef),
|
||||
Indirect(SigRef, Value),
|
||||
|
|
@ -532,7 +534,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
};
|
||||
|
||||
self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
|
||||
let call_args = return_ptr
|
||||
let mut call_args = return_ptr
|
||||
.into_iter()
|
||||
.chain(first_arg_override.into_iter())
|
||||
.chain(
|
||||
|
|
@ -545,40 +547,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
)
|
||||
.collect::<Vec<Value>>();
|
||||
|
||||
let call_inst = match func_ref {
|
||||
// FIXME: Find a cleaner way to support varargs.
|
||||
if fn_abi.c_variadic {
|
||||
adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args);
|
||||
}
|
||||
|
||||
match func_ref {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
|
||||
CallTarget::Indirect(sig, func_ptr) => {
|
||||
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME find a cleaner way to support varargs
|
||||
if fn_sig.c_variadic() {
|
||||
if !matches!(fn_sig.abi(), Abi::C { .. }) {
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
|
||||
);
|
||||
}
|
||||
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
|
||||
let abi_params = call_args
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let ty = fx.bcx.func.dfg.value_type(arg);
|
||||
if !ty.is_int() {
|
||||
// FIXME set %al to upperbound on float args once floats are supported
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Non int ty {:?} for variadic call", ty),
|
||||
);
|
||||
}
|
||||
AbiParam::new(ty)
|
||||
})
|
||||
.collect::<Vec<AbiParam>>();
|
||||
fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
|
||||
}
|
||||
|
||||
call_inst
|
||||
});
|
||||
|
||||
if let Some(dest) = target {
|
||||
|
|
@ -587,6 +566,100 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
} else {
|
||||
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
|
||||
}
|
||||
|
||||
fn adjust_call_for_c_variadic<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
source_info: mir::SourceInfo,
|
||||
target: CallTarget,
|
||||
call_args: &mut Vec<Value>,
|
||||
) {
|
||||
if fn_abi.conv != Conv::C {
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Variadic call for non-C abi {:?}", fn_abi.conv),
|
||||
);
|
||||
}
|
||||
let sig_ref = match target {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
|
||||
CallTarget::Indirect(sig_ref, _) => sig_ref,
|
||||
};
|
||||
// `mem::take()` the `params` so that `fx.bcx` can be used below.
|
||||
let mut abi_params = mem::take(&mut fx.bcx.func.dfg.signatures[sig_ref].params);
|
||||
|
||||
// Recalculate the parameters in the signature to ensure the signature contains the variadic arguments.
|
||||
let has_return_arg = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
// Drop everything except the return argument (if there is one).
|
||||
abi_params.truncate(if has_return_arg { 1 } else { 0 });
|
||||
// Add the fixed arguments.
|
||||
abi_params.extend(
|
||||
fn_abi.args[..fn_abi.fixed_count as usize]
|
||||
.iter()
|
||||
.flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()),
|
||||
);
|
||||
let fixed_arg_count = abi_params.len();
|
||||
// Add the variadic arguments.
|
||||
abi_params.extend(
|
||||
fn_abi.args[fn_abi.fixed_count as usize..]
|
||||
.iter()
|
||||
.flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()),
|
||||
);
|
||||
|
||||
if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" {
|
||||
// Add any padding arguments needed for Apple AArch64.
|
||||
// There's no need to pad the argument list unless variadic arguments are actually being
|
||||
// passed.
|
||||
if abi_params.len() > fixed_arg_count {
|
||||
// 128-bit integers take 2 registers, and everything else takes 1.
|
||||
// FIXME: Add support for non-integer types
|
||||
// This relies on the checks below to ensure all arguments are integer types and
|
||||
// that the ABI is "C".
|
||||
// The return argument isn't counted as it goes in its own dedicated register.
|
||||
let integer_registers_used: usize = abi_params
|
||||
[if has_return_arg { 1 } else { 0 }..fixed_arg_count]
|
||||
.iter()
|
||||
.map(|arg| if arg.value_type.bits() == 128 { 2 } else { 1 })
|
||||
.sum();
|
||||
// The ABI uses 8 registers before it starts pushing arguments to the stack. Pad out
|
||||
// the registers if needed to ensure the variadic arguments are passed on the stack.
|
||||
if integer_registers_used < 8 {
|
||||
abi_params.splice(
|
||||
fixed_arg_count..fixed_arg_count,
|
||||
(integer_registers_used..8).map(|_| AbiParam::new(types::I64)),
|
||||
);
|
||||
call_args.splice(
|
||||
fixed_arg_count..fixed_arg_count,
|
||||
(integer_registers_used..8).map(|_| fx.bcx.ins().iconst(types::I64, 0)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// `StructArgument` is not currently used by the `aarch64` ABI, and is therefore not
|
||||
// handled when calculating how many padding arguments to use. Assert that this remains
|
||||
// the case.
|
||||
assert!(abi_params.iter().all(|param| matches!(
|
||||
param.purpose,
|
||||
// The only purposes used are `Normal` and `StructReturn`.
|
||||
ArgumentPurpose::Normal | ArgumentPurpose::StructReturn
|
||||
)));
|
||||
}
|
||||
|
||||
// Check all parameters are integers.
|
||||
for param in abi_params.iter() {
|
||||
if !param.value_type.is_int() {
|
||||
// FIXME: Set %al to upperbound on float args once floats are supported.
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Non int ty {:?} for variadic call", param.value_type),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(abi_params.len(), call_args.len());
|
||||
|
||||
// Put the `AbiParam`s back in the signature.
|
||||
fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_drop<'tcx>(
|
||||
|
|
|
|||
|
|
@ -11,15 +11,10 @@ use rustc_session::config::OomStrategy;
|
|||
use crate::prelude::*;
|
||||
|
||||
/// Returns whether an allocator shim was created
|
||||
pub(crate) fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
) -> bool {
|
||||
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
||||
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||
codegen_inner(
|
||||
module,
|
||||
unwind_context,
|
||||
kind,
|
||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||
tcx.sess.opts.unstable_opts.oom,
|
||||
|
|
@ -28,8 +23,7 @@ pub(crate) fn codegen(
|
|||
}
|
||||
|
||||
fn codegen_inner(
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
module: &mut dyn Module,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
oom_strategy: OomStrategy,
|
||||
|
|
@ -67,7 +61,6 @@ fn codegen_inner(
|
|||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
unwind_context,
|
||||
sig,
|
||||
&global_fn_name(method.name),
|
||||
&default_fn_name(method.name),
|
||||
|
|
@ -82,7 +75,6 @@ fn codegen_inner(
|
|||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
unwind_context,
|
||||
sig,
|
||||
"__rust_alloc_error_handler",
|
||||
&alloc_error_handler_name(alloc_error_handler_kind),
|
||||
|
|
|
|||
|
|
@ -249,9 +249,7 @@ pub(crate) fn compile_fn(
|
|||
}
|
||||
|
||||
// Define debuginfo for function
|
||||
let isa = module.isa();
|
||||
let debug_context = &mut cx.debug_context;
|
||||
let unwind_context = &mut cx.unwind_context;
|
||||
cx.profiler.generic_activity("generate debug info").run(|| {
|
||||
if let Some(debug_context) = debug_context {
|
||||
codegened_func.func_debug_cx.unwrap().finalize(
|
||||
|
|
@ -260,7 +258,6 @@ pub(crate) fn compile_fn(
|
|||
context,
|
||||
);
|
||||
}
|
||||
unwind_context.add_function(codegened_func.func_id, &context, isa);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -909,7 +906,7 @@ fn codegen_stmt<'tcx>(
|
|||
| StatementKind::PlaceMention(..)
|
||||
| StatementKind::AscribeUserType(..) => {}
|
||||
|
||||
StatementKind::Coverage { .. } => fx.tcx.dcx().fatal("-Zcoverage is unimplemented"),
|
||||
StatementKind::Coverage { .. } => unreachable!(),
|
||||
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
|
||||
// We ignore `assume` intrinsics, they are only useful for optimizations
|
||||
NonDivergingIntrinsic::Assume(_) => {}
|
||||
|
|
|
|||
|
|
@ -247,7 +247,6 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
|
|||
|
||||
pub(crate) fn create_wrapper_function(
|
||||
module: &mut dyn Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
sig: Signature,
|
||||
wrapper_name: &str,
|
||||
callee_name: &str,
|
||||
|
|
@ -280,7 +279,6 @@ pub(crate) fn create_wrapper_function(
|
|||
bcx.finalize();
|
||||
}
|
||||
module.define_function(wrapper_func_id, &mut ctx).unwrap();
|
||||
unwind_context.add_function(wrapper_func_id, &ctx, module.isa());
|
||||
}
|
||||
|
||||
pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
||||
|
|
@ -395,6 +393,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
|
||||
// a way to specify stack slot alignment.
|
||||
size: (size + abi_align - 1) / abi_align * abi_align,
|
||||
align_shift: 4,
|
||||
});
|
||||
Pointer::stack_slot(stack_slot)
|
||||
} else {
|
||||
|
|
@ -405,6 +404,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
|
||||
// a way to specify stack slot alignment.
|
||||
size: (size + align) / abi_align * abi_align,
|
||||
align_shift: 4,
|
||||
});
|
||||
let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0);
|
||||
let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align));
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use rustc_session::Session;
|
|||
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
use crate::global_asm::GlobalAsmConfig;
|
||||
use crate::unwind_module::UnwindModule;
|
||||
use crate::{prelude::*, BackendConfig};
|
||||
|
||||
struct ModuleCodegenResult {
|
||||
|
|
@ -318,7 +319,11 @@ fn produce_final_output_artifacts(
|
|||
// These are used in linking steps and will be cleaned up afterward.
|
||||
}
|
||||
|
||||
fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {
|
||||
fn make_module(
|
||||
sess: &Session,
|
||||
backend_config: &BackendConfig,
|
||||
name: String,
|
||||
) -> UnwindModule<ObjectModule> {
|
||||
let isa = crate::build_isa(sess, backend_config);
|
||||
|
||||
let mut builder =
|
||||
|
|
@ -327,16 +332,15 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) ->
|
|||
// is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
|
||||
// can easily double the amount of time necessary to perform linking.
|
||||
builder.per_function_section(sess.opts.unstable_opts.function_sections.unwrap_or(false));
|
||||
ObjectModule::new(builder)
|
||||
UnwindModule::new(ObjectModule::new(builder), true)
|
||||
}
|
||||
|
||||
fn emit_cgu(
|
||||
output_filenames: &OutputFilenames,
|
||||
prof: &SelfProfilerRef,
|
||||
name: String,
|
||||
module: ObjectModule,
|
||||
module: UnwindModule<ObjectModule>,
|
||||
debug: Option<DebugContext>,
|
||||
unwind_context: UnwindContext,
|
||||
global_asm_object_file: Option<PathBuf>,
|
||||
producer: &str,
|
||||
) -> Result<ModuleCodegenResult, String> {
|
||||
|
|
@ -346,8 +350,6 @@ fn emit_cgu(
|
|||
debug.emit(&mut product);
|
||||
}
|
||||
|
||||
unwind_context.emit(&mut product);
|
||||
|
||||
let module_regular = emit_module(
|
||||
output_filenames,
|
||||
prof,
|
||||
|
|
@ -494,7 +496,6 @@ fn module_codegen(
|
|||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config.clone(),
|
||||
module.isa(),
|
||||
tcx.sess.opts.debuginfo != DebugInfo::None,
|
||||
cgu_name,
|
||||
|
|
@ -531,13 +532,7 @@ fn module_codegen(
|
|||
}
|
||||
}
|
||||
}
|
||||
crate::main_shim::maybe_create_entry_wrapper(
|
||||
tcx,
|
||||
&mut module,
|
||||
&mut cx.unwind_context,
|
||||
false,
|
||||
cgu.is_primary(),
|
||||
);
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, false, cgu.is_primary());
|
||||
|
||||
let cgu_name = cgu.name().as_str().to_owned();
|
||||
|
||||
|
|
@ -571,7 +566,6 @@ fn module_codegen(
|
|||
cgu_name,
|
||||
module,
|
||||
cx.debug_context,
|
||||
cx.unwind_context,
|
||||
global_asm_object_file,
|
||||
&producer,
|
||||
)
|
||||
|
|
@ -665,13 +659,10 @@ pub(crate) fn run_aot(
|
|||
});
|
||||
|
||||
let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
|
||||
let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true);
|
||||
let created_alloc_shim =
|
||||
crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context);
|
||||
let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
|
||||
|
||||
let allocator_module = if created_alloc_shim {
|
||||
let mut product = allocator_module.finish();
|
||||
allocator_unwind_context.emit(&mut product);
|
||||
let product = allocator_module.finish();
|
||||
|
||||
match emit_module(
|
||||
tcx.output_filenames(()),
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ use rustc_session::Session;
|
|||
use rustc_span::Symbol;
|
||||
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
use crate::unwind_module::UnwindModule;
|
||||
use crate::{prelude::*, BackendConfig};
|
||||
use crate::{CodegenCx, CodegenMode};
|
||||
|
||||
struct JitState {
|
||||
backend_config: BackendConfig,
|
||||
jit_module: JITModule,
|
||||
jit_module: UnwindModule<JITModule>,
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
|
|
@ -63,7 +63,7 @@ fn create_jit_module(
|
|||
tcx: TyCtxt<'_>,
|
||||
backend_config: &BackendConfig,
|
||||
hotswap: bool,
|
||||
) -> (JITModule, CodegenCx) {
|
||||
) -> (UnwindModule<JITModule>, CodegenCx) {
|
||||
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, backend_config);
|
||||
|
|
@ -72,17 +72,11 @@ fn create_jit_module(
|
|||
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
|
||||
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
|
||||
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
|
||||
let mut jit_module = JITModule::new(jit_builder);
|
||||
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config.clone(),
|
||||
jit_module.isa(),
|
||||
false,
|
||||
Symbol::intern("dummy_cgu_name"),
|
||||
);
|
||||
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"));
|
||||
|
||||
crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context);
|
||||
crate::allocator::codegen(tcx, &mut jit_module);
|
||||
|
||||
(jit_module, cx)
|
||||
}
|
||||
|
|
@ -128,7 +122,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
|||
);
|
||||
}
|
||||
CodegenMode::JitLazy => {
|
||||
codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst)
|
||||
codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
|
||||
}
|
||||
},
|
||||
MonoItem::Static(def_id) => {
|
||||
|
|
@ -146,18 +140,11 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
|||
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
|
||||
}
|
||||
|
||||
crate::main_shim::maybe_create_entry_wrapper(
|
||||
tcx,
|
||||
&mut jit_module,
|
||||
&mut cx.unwind_context,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, true, true);
|
||||
|
||||
tcx.dcx().abort_if_errors();
|
||||
|
||||
jit_module.finalize_definitions().unwrap();
|
||||
unsafe { cx.unwind_context.register_jit(&jit_module) };
|
||||
jit_module.finalize_definitions();
|
||||
|
||||
println!(
|
||||
"Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed"
|
||||
|
|
@ -177,12 +164,12 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
|||
call_conv: jit_module.target_config().default_call_conv,
|
||||
};
|
||||
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
|
||||
let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);
|
||||
let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
|
||||
|
||||
LAZY_JIT_STATE.with(|lazy_jit_state| {
|
||||
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
|
||||
assert!(lazy_jit_state.is_none());
|
||||
*lazy_jit_state = Some(JitState { backend_config, jit_module });
|
||||
*lazy_jit_state = Some(JitState { jit_module });
|
||||
});
|
||||
|
||||
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
|
||||
|
|
@ -268,7 +255,6 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
|
||||
let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
|
||||
let jit_module = &mut lazy_jit_state.jit_module;
|
||||
let backend_config = lazy_jit_state.backend_config.clone();
|
||||
|
||||
let name = tcx.symbol_name(instance).name;
|
||||
let sig = crate::abi::get_function_sig(
|
||||
|
|
@ -278,7 +264,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
);
|
||||
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
|
||||
|
||||
let current_ptr = jit_module.read_got_entry(func_id);
|
||||
let current_ptr = jit_module.module.read_got_entry(func_id);
|
||||
|
||||
// If the function's GOT entry has already been updated to point at something other
|
||||
// than the shim trampoline, don't re-jit but just return the new pointer instead.
|
||||
|
|
@ -288,11 +274,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
return current_ptr;
|
||||
}
|
||||
|
||||
jit_module.prepare_for_function_redefine(func_id).unwrap();
|
||||
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config,
|
||||
jit_module.isa(),
|
||||
false,
|
||||
Symbol::intern("dummy_cgu_name"),
|
||||
|
|
@ -300,9 +285,8 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
|
||||
|
||||
assert!(cx.global_asm.is_empty());
|
||||
jit_module.finalize_definitions().unwrap();
|
||||
unsafe { cx.unwind_context.register_jit(&jit_module) };
|
||||
jit_module.get_finalized_function(func_id)
|
||||
jit_module.finalize_definitions();
|
||||
jit_module.module.get_finalized_function(func_id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -310,7 +294,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
fn dep_symbol_lookup_fn(
|
||||
sess: &Session,
|
||||
crate_info: CrateInfo,
|
||||
) -> Box<dyn Fn(&str) -> Option<*const u8>> {
|
||||
) -> Box<dyn Fn(&str) -> Option<*const u8> + Send> {
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
|
||||
let mut dylib_paths = Vec::new();
|
||||
|
|
@ -362,9 +346,8 @@ fn dep_symbol_lookup_fn(
|
|||
|
||||
fn codegen_shim<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cx: &mut CodegenCx,
|
||||
cached_context: &mut Context,
|
||||
module: &mut JITModule,
|
||||
module: &mut UnwindModule<JITModule>,
|
||||
inst: Instance<'tcx>,
|
||||
) {
|
||||
let pointer_type = module.target_config().pointer_type();
|
||||
|
|
@ -413,5 +396,4 @@ fn codegen_shim<'tcx>(
|
|||
trampoline_builder.ins().return_(&ret_vals);
|
||||
|
||||
module.define_function(func_id, context).unwrap();
|
||||
cx.unwind_context.add_function(func_id, context, module.isa());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,13 +113,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
|
|||
);
|
||||
let sig =
|
||||
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
|
||||
create_wrapper_function(
|
||||
fx.module,
|
||||
&mut fx.cx.unwind_context,
|
||||
sig,
|
||||
&wrapper_name,
|
||||
symbol.name,
|
||||
);
|
||||
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
|
||||
|
||||
CInlineAsmOperand::Symbol { symbol: wrapper_name }
|
||||
} else {
|
||||
|
|
@ -283,13 +277,7 @@ pub(crate) fn codegen_naked_asm<'tcx>(
|
|||
);
|
||||
let sig =
|
||||
get_function_sig(tcx, module.target_config().default_call_conv, instance);
|
||||
create_wrapper_function(
|
||||
module,
|
||||
&mut cx.unwind_context,
|
||||
sig,
|
||||
&wrapper_name,
|
||||
symbol.name,
|
||||
);
|
||||
create_wrapper_function(module, sig, &wrapper_name, symbol.name);
|
||||
|
||||
CInlineAsmOperand::Symbol { symbol: wrapper_name }
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -459,11 +459,20 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
|
||||
let value = fx.bcx.ins().x86_cvtt2dq(types::I32X4, a);
|
||||
let cvalue = CValue::by_val(value, ret.layout());
|
||||
ret.write_cvalue(fx, cvalue);
|
||||
}
|
||||
"llvm.x86.sse2.cvtps2dq" => {
|
||||
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_epi32
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
|
||||
// Using inline asm instead of fcvt_to_sint_sat as unrepresentable values are turned
|
||||
// into 0x80000000 for which Cranelift doesn't have a native instruction.
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("cvttps2dq xmm0, xmm0"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))],
|
||||
&[CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
_late: true,
|
||||
|
|
@ -1416,6 +1425,36 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
ret.write_cvalue(fx, res);
|
||||
}
|
||||
|
||||
"llvm.x86.rdtsc" => {
|
||||
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdtsc&ig_expand=5273
|
||||
|
||||
let res_place = CPlace::new_stack_slot(
|
||||
fx,
|
||||
fx.layout_of(Ty::new_tup(fx.tcx, &[fx.tcx.types.u32, fx.tcx.types.u32])),
|
||||
);
|
||||
let eax_place = res_place.place_field(fx, FieldIdx::new(0));
|
||||
let edx_place = res_place.place_field(fx, FieldIdx::new(1));
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("rdtsc".to_string())],
|
||||
&[
|
||||
CInlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
late: true,
|
||||
place: Some(eax_place),
|
||||
},
|
||||
CInlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
|
||||
late: true,
|
||||
place: Some(edx_place),
|
||||
},
|
||||
],
|
||||
InlineAsmOptions::NOSTACK | InlineAsmOptions::NOMEM,
|
||||
);
|
||||
let res = res_place.to_cvalue(fx);
|
||||
ret.write_cvalue_transmute(fx, res);
|
||||
}
|
||||
|
||||
_ => {
|
||||
fx.tcx
|
||||
.dcx()
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ mod pretty_clif;
|
|||
mod toolchain;
|
||||
mod trap;
|
||||
mod unsize;
|
||||
mod unwind_module;
|
||||
mod value_and_place;
|
||||
mod vtable;
|
||||
|
||||
|
|
@ -130,22 +131,13 @@ struct CodegenCx {
|
|||
global_asm: String,
|
||||
inline_asm_index: Cell<usize>,
|
||||
debug_context: Option<DebugContext>,
|
||||
unwind_context: UnwindContext,
|
||||
cgu_name: Symbol,
|
||||
}
|
||||
|
||||
impl CodegenCx {
|
||||
fn new(
|
||||
tcx: TyCtxt<'_>,
|
||||
backend_config: BackendConfig,
|
||||
isa: &dyn TargetIsa,
|
||||
debug_info: bool,
|
||||
cgu_name: Symbol,
|
||||
) -> Self {
|
||||
fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol) -> Self {
|
||||
assert_eq!(pointer_ty(tcx), isa.pointer_type());
|
||||
|
||||
let unwind_context =
|
||||
UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
|
||||
let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
|
||||
Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
|
||||
} else {
|
||||
|
|
@ -158,7 +150,6 @@ impl CodegenCx {
|
|||
global_asm: String::new(),
|
||||
inline_asm_index: Cell::new(0),
|
||||
debug_context,
|
||||
unwind_context,
|
||||
cgu_name,
|
||||
}
|
||||
}
|
||||
|
|
@ -175,7 +166,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
use rustc_session::config::Lto;
|
||||
use rustc_session::config::{InstrumentCoverage, Lto};
|
||||
match sess.lto() {
|
||||
Lto::No | Lto::ThinLocal => {}
|
||||
Lto::Thin | Lto::Fat => {
|
||||
|
|
@ -183,6 +174,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
}
|
||||
}
|
||||
|
||||
if sess.opts.cg.instrument_coverage() != InstrumentCoverage::No {
|
||||
sess.dcx()
|
||||
.fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
|
||||
}
|
||||
|
||||
let mut config = self.config.borrow_mut();
|
||||
if config.is_none() {
|
||||
let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use crate::prelude::*;
|
|||
/// users main function.
|
||||
pub(crate) fn maybe_create_entry_wrapper(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
module: &mut dyn Module,
|
||||
is_jit: bool,
|
||||
is_primary_cgu: bool,
|
||||
) {
|
||||
|
|
@ -36,12 +35,11 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
return;
|
||||
}
|
||||
|
||||
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
|
||||
create_entry_fn(tcx, module, main_def_id, is_jit, is_main_fn, sigpipe);
|
||||
|
||||
fn create_entry_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
m: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
m: &mut dyn Module,
|
||||
rust_main_def_id: DefId,
|
||||
ignore_lang_start_wrapper: bool,
|
||||
is_main_fn: bool,
|
||||
|
|
@ -170,7 +168,5 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
if let Err(err) = m.define_function(cmain_func_id, &mut ctx) {
|
||||
tcx.dcx().fatal(format!("entry symbol `{entry_name}` defined multiple times: {err}"));
|
||||
}
|
||||
|
||||
unwind_context.add_function(cmain_func_id, &ctx, m.isa());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
115
compiler/rustc_codegen_cranelift/src/unwind_module.rs
Normal file
115
compiler/rustc_codegen_cranelift/src/unwind_module.rs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
use cranelift_codegen::control::ControlPlane;
|
||||
use cranelift_codegen::ir::{Function, Signature};
|
||||
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
|
||||
use cranelift_codegen::{Context, FinalizedMachReloc};
|
||||
use cranelift_module::{
|
||||
DataDescription, DataId, FuncId, FuncOrDataId, Linkage, Module, ModuleDeclarations,
|
||||
ModuleResult,
|
||||
};
|
||||
use cranelift_object::{ObjectModule, ObjectProduct};
|
||||
|
||||
use crate::UnwindContext;
|
||||
|
||||
/// A wrapper around a [Module] which adds any defined function to the [UnwindContext].
|
||||
pub(crate) struct UnwindModule<T> {
|
||||
pub(crate) module: T,
|
||||
unwind_context: UnwindContext,
|
||||
}
|
||||
|
||||
impl<T: Module> UnwindModule<T> {
|
||||
pub(crate) fn new(module: T, pic_eh_frame: bool) -> Self {
|
||||
let unwind_context = UnwindContext::new(module.isa(), pic_eh_frame);
|
||||
UnwindModule { module, unwind_context }
|
||||
}
|
||||
}
|
||||
|
||||
impl UnwindModule<ObjectModule> {
|
||||
pub(crate) fn finish(self) -> ObjectProduct {
|
||||
let mut product = self.module.finish();
|
||||
self.unwind_context.emit(&mut product);
|
||||
product
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "jit")]
|
||||
impl UnwindModule<cranelift_jit::JITModule> {
|
||||
pub(crate) fn finalize_definitions(&mut self) {
|
||||
self.module.finalize_definitions().unwrap();
|
||||
let prev_unwind_context = std::mem::replace(
|
||||
&mut self.unwind_context,
|
||||
UnwindContext::new(self.module.isa(), false),
|
||||
);
|
||||
unsafe { prev_unwind_context.register_jit(&self.module) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Module> Module for UnwindModule<T> {
|
||||
fn isa(&self) -> &dyn TargetIsa {
|
||||
self.module.isa()
|
||||
}
|
||||
|
||||
fn declarations(&self) -> &ModuleDeclarations {
|
||||
self.module.declarations()
|
||||
}
|
||||
|
||||
fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
|
||||
self.module.get_name(name)
|
||||
}
|
||||
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.module.target_config()
|
||||
}
|
||||
|
||||
fn declare_function(
|
||||
&mut self,
|
||||
name: &str,
|
||||
linkage: Linkage,
|
||||
signature: &Signature,
|
||||
) -> ModuleResult<FuncId> {
|
||||
self.module.declare_function(name, linkage, signature)
|
||||
}
|
||||
|
||||
fn declare_anonymous_function(&mut self, signature: &Signature) -> ModuleResult<FuncId> {
|
||||
self.module.declare_anonymous_function(signature)
|
||||
}
|
||||
|
||||
fn declare_data(
|
||||
&mut self,
|
||||
name: &str,
|
||||
linkage: Linkage,
|
||||
writable: bool,
|
||||
tls: bool,
|
||||
) -> ModuleResult<DataId> {
|
||||
self.module.declare_data(name, linkage, writable, tls)
|
||||
}
|
||||
|
||||
fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
|
||||
self.module.declare_anonymous_data(writable, tls)
|
||||
}
|
||||
|
||||
fn define_function_with_control_plane(
|
||||
&mut self,
|
||||
func: FuncId,
|
||||
ctx: &mut Context,
|
||||
ctrl_plane: &mut ControlPlane,
|
||||
) -> ModuleResult<()> {
|
||||
self.module.define_function_with_control_plane(func, ctx, ctrl_plane)?;
|
||||
self.unwind_context.add_function(func, ctx, self.module.isa());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn define_function_bytes(
|
||||
&mut self,
|
||||
_func_id: FuncId,
|
||||
_func: &Function,
|
||||
_alignment: u64,
|
||||
_bytes: &[u8],
|
||||
_relocs: &[FinalizedMachReloc],
|
||||
) -> ModuleResult<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
|
||||
self.module.define_data(data_id, data)
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
global
|
||||
// TODO(antoyo): set linkage.
|
||||
}
|
||||
|
||||
pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
|
||||
|
|
@ -239,19 +252,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
const_alloc_to_gcc(self, alloc)
|
||||
}
|
||||
|
||||
fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
self.context
|
||||
.new_array_access(None, base_addr, self.const_usize(offset.bytes()))
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ use crate::callee::get_fn;
|
|||
use crate::common::SignType;
|
||||
|
||||
pub struct CodegenCx<'gcc, 'tcx> {
|
||||
pub check_overflow: bool,
|
||||
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
pub context: &'gcc Context<'gcc>,
|
||||
|
||||
|
|
@ -134,8 +133,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
supports_128bit_integers: bool,
|
||||
) -> Self {
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
|
|
@ -271,7 +268,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
let mut cx = Self {
|
||||
check_overflow,
|
||||
codegen_unit,
|
||||
context,
|
||||
current_func: RefCell::new(None),
|
||||
|
|
@ -511,10 +507,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
&self.tcx.sess
|
||||
}
|
||||
|
||||
fn check_overflow(&self) -> bool {
|
||||
self.check_overflow
|
||||
}
|
||||
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
|
||||
self.codegen_unit
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,13 +89,34 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
ty::FloatTy::F128 => self.type_f128(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_i1(&self) -> Type<'gcc> {
|
||||
pub fn type_i1(&self) -> Type<'gcc> {
|
||||
self.bool_type
|
||||
}
|
||||
|
||||
pub fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
|
||||
let types = fields.to_vec();
|
||||
if let Some(typ) = self.struct_types.borrow().get(fields) {
|
||||
return *typ;
|
||||
}
|
||||
let fields: Vec<_> = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, field)| {
|
||||
self.context.new_field(None, *field, format!("field{}_TODO", index))
|
||||
})
|
||||
.collect();
|
||||
let typ = self.context.new_struct_type(None, "struct", &fields).as_type();
|
||||
if packed {
|
||||
#[cfg(feature = "master")]
|
||||
typ.set_packed();
|
||||
}
|
||||
self.struct_types.borrow_mut().insert(types, typ);
|
||||
typ
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_i8(&self) -> Type<'gcc> {
|
||||
self.i8_type
|
||||
}
|
||||
|
|
@ -131,7 +152,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
fn type_f64(&self) -> Type<'gcc> {
|
||||
self.double_type
|
||||
}
|
||||
|
||||
|
||||
fn type_f128(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
}
|
||||
|
|
@ -140,27 +161,6 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
self.context.new_function_pointer_type(None, return_type, params, false)
|
||||
}
|
||||
|
||||
fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
|
||||
let types = fields.to_vec();
|
||||
if let Some(typ) = self.struct_types.borrow().get(fields) {
|
||||
return *typ;
|
||||
}
|
||||
let fields: Vec<_> = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, field)| {
|
||||
self.context.new_field(None, *field, format!("field{}_TODO", index))
|
||||
})
|
||||
.collect();
|
||||
let typ = self.context.new_struct_type(None, "struct", &fields).as_type();
|
||||
if packed {
|
||||
#[cfg(feature = "master")]
|
||||
typ.set_packed();
|
||||
}
|
||||
self.struct_types.borrow_mut().insert(types, typ);
|
||||
typ
|
||||
}
|
||||
|
||||
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||
if self.is_int_type_or_bool(typ) {
|
||||
TypeKind::Integer
|
||||
|
|
|
|||
|
|
@ -329,10 +329,6 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
const_alloc_to_llvm(self, alloc, /*static*/ false)
|
||||
}
|
||||
|
||||
fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||
self.const_bitcast(val, ty)
|
||||
}
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
unsafe {
|
||||
llvm::LLVMConstInBoundsGEP2(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
|
|||
use crate::callee::get_fn;
|
||||
use crate::coverageinfo;
|
||||
use crate::debuginfo;
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm;
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -43,7 +44,6 @@ use std::str;
|
|||
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
|
||||
pub struct CodegenCx<'ll, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
pub check_overflow: bool,
|
||||
pub use_dll_storage_attrs: bool,
|
||||
pub tls_model: llvm::ThreadLocalMode,
|
||||
|
||||
|
|
@ -441,8 +441,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
// start) and then strongly recommending static linkage on Windows!
|
||||
let use_dll_storage_attrs = tcx.sess.target.is_like_windows;
|
||||
|
||||
let check_overflow = tcx.sess.overflow_checks();
|
||||
|
||||
let tls_model = to_llvm_tls_model(tcx.sess.tls_model());
|
||||
|
||||
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
|
||||
|
|
@ -466,7 +464,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
|
||||
CodegenCx {
|
||||
tcx,
|
||||
check_overflow,
|
||||
use_dll_storage_attrs,
|
||||
tls_model,
|
||||
llmod,
|
||||
|
|
@ -522,6 +519,15 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
&self.vtables
|
||||
}
|
||||
|
||||
fn apply_vcall_visibility_metadata(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);
|
||||
}
|
||||
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
|
||||
get_fn(self, instance)
|
||||
}
|
||||
|
|
@ -596,10 +602,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
self.tcx.sess
|
||||
}
|
||||
|
||||
fn check_overflow(&self) -> bool {
|
||||
self.check_overflow
|
||||
}
|
||||
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
|
||||
self.codegen_unit
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1449,12 +1449,18 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
|
|||
.di_node
|
||||
}
|
||||
|
||||
fn vcall_visibility_metadata<'ll, 'tcx>(
|
||||
pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
// FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
|
||||
// LLVM at the moment.
|
||||
if !cx.sess().opts.unstable_opts.virtual_function_elimination || cx.sess().lto() != Lto::Fat {
|
||||
return;
|
||||
}
|
||||
|
||||
enum VCallVisibility {
|
||||
Public = 0,
|
||||
LinkageUnit = 1,
|
||||
|
|
@ -1531,12 +1537,6 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
|
|||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
vtable: &'ll Value,
|
||||
) {
|
||||
// FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
|
||||
// LLVM at the moment.
|
||||
if cx.sess().opts.unstable_opts.virtual_function_elimination && cx.sess().lto() == Lto::Fat {
|
||||
vcall_visibility_metadata(cx, ty, poly_trait_ref, vtable);
|
||||
}
|
||||
|
||||
if cx.dbg_cx.is_none() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,10 +274,11 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
||||
}
|
||||
|
||||
fn print(&self, req: &PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
||||
use std::fmt::Write;
|
||||
match req.kind {
|
||||
PrintKind::RelocationModels => {
|
||||
writeln!(out, "Available relocation models:");
|
||||
writeln!(out, "Available relocation models:").unwrap();
|
||||
for name in &[
|
||||
"static",
|
||||
"pic",
|
||||
|
|
@ -288,25 +289,25 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
"ropi-rwpi",
|
||||
"default",
|
||||
] {
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::CodeModels => {
|
||||
writeln!(out, "Available code models:");
|
||||
writeln!(out, "Available code models:").unwrap();
|
||||
for name in &["tiny", "small", "kernel", "medium", "large"] {
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::TlsModels => {
|
||||
writeln!(out, "Available TLS models:");
|
||||
writeln!(out, "Available TLS models:").unwrap();
|
||||
for name in
|
||||
&["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"]
|
||||
{
|
||||
writeln!(out, " {name}");
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out);
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::StackProtectorStrategies => {
|
||||
writeln!(
|
||||
|
|
@ -332,7 +333,8 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
none
|
||||
Do not generate stack canaries.
|
||||
"#
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
_other => llvm_util::print(req, out, sess),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use crate::errors::{
|
|||
use crate::llvm;
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||
use rustc_codegen_ssa::traits::PrintBackendInfo;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_fs_util::path_to_c_string;
|
||||
|
|
@ -18,6 +17,7 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
|||
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
|
||||
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
use std::fmt::Write;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
|
@ -372,7 +372,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
|
|||
ret
|
||||
}
|
||||
|
||||
fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &llvm::TargetMachine) {
|
||||
fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMachine) {
|
||||
let mut llvm_target_features = llvm_target_features(tm);
|
||||
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
|
||||
let mut rustc_target_features = sess
|
||||
|
|
@ -412,24 +412,26 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll
|
|||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
writeln!(out, "Features supported by rustc for this target:");
|
||||
writeln!(out, "Features supported by rustc for this target:").unwrap();
|
||||
for (feature, desc) in &rustc_target_features {
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.");
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap();
|
||||
}
|
||||
writeln!(out, "\nCode-generation features supported by LLVM for this target:");
|
||||
writeln!(out, "\nCode-generation features supported by LLVM for this target:").unwrap();
|
||||
for (feature, desc) in &llvm_target_features {
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.");
|
||||
writeln!(out, " {feature:max_feature_len$} - {desc}.").unwrap();
|
||||
}
|
||||
if llvm_target_features.is_empty() {
|
||||
writeln!(out, " Target features listing is not supported by this LLVM version.");
|
||||
writeln!(out, " Target features listing is not supported by this LLVM version.")
|
||||
.unwrap();
|
||||
}
|
||||
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.");
|
||||
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n");
|
||||
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],");
|
||||
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n");
|
||||
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.").unwrap();
|
||||
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n")
|
||||
.unwrap();
|
||||
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],").unwrap();
|
||||
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||
require_inited();
|
||||
let tm = create_informational_target_machine(sess);
|
||||
match req.kind {
|
||||
|
|
@ -440,9 +442,9 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess
|
|||
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
||||
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
||||
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
|
||||
let out = &mut *(out as *mut &mut dyn PrintBackendInfo);
|
||||
let out = &mut *(out as *mut &mut String);
|
||||
let bytes = slice::from_raw_parts(string as *const u8, len);
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes));
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap();
|
||||
}
|
||||
unsafe {
|
||||
llvm::LLVMRustPrintTargetCPUs(
|
||||
|
|
|
|||
|
|
@ -127,13 +127,24 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn type_i1(&self) -> &'ll Type {
|
||||
pub(crate) fn type_i1(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt1TypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(
|
||||
self.llcx,
|
||||
els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
packed as Bool,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn type_i8(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt8TypeInContext(self.llcx) }
|
||||
}
|
||||
|
|
@ -178,17 +189,6 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
|
||||
}
|
||||
|
||||
fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(
|
||||
self.llcx,
|
||||
els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
packed as Bool,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn type_kind(&self, ty: &'ll Type) -> TypeKind {
|
||||
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ use tempfile::Builder as TempFileBuilder;
|
|||
|
||||
use itertools::Itertools;
|
||||
use std::collections::BTreeSet;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{read, File, OpenOptions};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::ops::Deref;
|
||||
|
|
@ -1306,12 +1306,12 @@ fn link_sanitizer_runtime(
|
|||
let filename = format!("rustc{channel}_rt.{name}");
|
||||
let path = find_sanitizer_runtime(sess, &filename);
|
||||
let rpath = path.to_str().expect("non-utf8 component in path");
|
||||
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||
linker.cc_args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||
linker.link_dylib_by_name(&filename, false, true);
|
||||
} else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" {
|
||||
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
|
||||
// compatible ASAN library.
|
||||
linker.arg("/INFERASANLIBS");
|
||||
linker.link_arg("/INFERASANLIBS");
|
||||
} else {
|
||||
let filename = format!("librustc{channel}_rt.{name}.a");
|
||||
let path = find_sanitizer_runtime(sess, &filename).join(&filename);
|
||||
|
|
@ -1888,9 +1888,9 @@ fn add_post_link_objects(
|
|||
/// FIXME: Determine where exactly these args need to be inserted.
|
||||
fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
||||
if let Some(args) = sess.target.pre_link_args.get(&flavor) {
|
||||
cmd.args(args.iter().map(Deref::deref));
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
cmd.args(&sess.opts.unstable_opts.pre_link_args);
|
||||
cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
|
||||
}
|
||||
|
||||
/// Add a link script embedded in the target, if applicable.
|
||||
|
|
@ -1908,8 +1908,7 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty
|
|||
sess.dcx().emit_fatal(errors::LinkScriptWriteFailure { path, error });
|
||||
}
|
||||
|
||||
cmd.arg("--script");
|
||||
cmd.arg(path);
|
||||
cmd.link_arg("--script").link_arg(path);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -1918,7 +1917,7 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty
|
|||
/// Add arbitrary "user defined" args defined from command line.
|
||||
/// FIXME: Determine where exactly these args need to be inserted.
|
||||
fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) {
|
||||
cmd.args(&sess.opts.cg.link_args);
|
||||
cmd.verbatim_args(&sess.opts.cg.link_args);
|
||||
}
|
||||
|
||||
/// Add arbitrary "late link" args defined by the target spec.
|
||||
|
|
@ -1936,15 +1935,15 @@ fn add_late_link_args(
|
|||
});
|
||||
if any_dynamic_crate {
|
||||
if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) {
|
||||
cmd.args(args.iter().map(Deref::deref));
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
} else {
|
||||
if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
|
||||
cmd.args(args.iter().map(Deref::deref));
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
}
|
||||
if let Some(args) = sess.target.late_link_args.get(&flavor) {
|
||||
cmd.args(args.iter().map(Deref::deref));
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1952,7 +1951,7 @@ fn add_late_link_args(
|
|||
/// FIXME: Determine where exactly these args need to be inserted.
|
||||
fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
||||
if let Some(args) = sess.target.post_link_args.get(&flavor) {
|
||||
cmd.args(args.iter().map(Deref::deref));
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2097,6 +2096,10 @@ fn add_rpath_args(
|
|||
codegen_results: &CodegenResults,
|
||||
out_filename: &Path,
|
||||
) {
|
||||
if !sess.target.has_rpath {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME (#2397): At some point we want to rpath our guesses as to
|
||||
// where extern libraries might live, based on the
|
||||
// add_lib_search_paths
|
||||
|
|
@ -2115,11 +2118,10 @@ fn add_rpath_args(
|
|||
let rpath_config = RPathConfig {
|
||||
libs: &*libs,
|
||||
out_filename: out_filename.to_path_buf(),
|
||||
has_rpath: sess.target.has_rpath,
|
||||
is_like_osx: sess.target.is_like_osx,
|
||||
linker_is_gnu: sess.target.linker_flavor.is_gnu(),
|
||||
};
|
||||
cmd.args(&rpath::get_rpath_flags(&rpath_config));
|
||||
cmd.cc_args(&rpath::get_rpath_flags(&rpath_config));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2378,7 +2380,7 @@ fn add_order_independent_options(
|
|||
} else {
|
||||
""
|
||||
};
|
||||
cmd.arg(format!("--dynamic-linker={prefix}ld.so.1"));
|
||||
cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1"));
|
||||
}
|
||||
|
||||
if sess.target.eh_frame_header {
|
||||
|
|
@ -2393,8 +2395,7 @@ fn add_order_independent_options(
|
|||
}
|
||||
|
||||
if sess.target.os == "emscripten" {
|
||||
cmd.arg("-s");
|
||||
cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
|
||||
cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
|
||||
"DISABLE_EXCEPTION_CATCHING=1"
|
||||
} else {
|
||||
"DISABLE_EXCEPTION_CATCHING=0"
|
||||
|
|
@ -2402,22 +2403,21 @@ fn add_order_independent_options(
|
|||
}
|
||||
|
||||
if flavor == LinkerFlavor::Llbc {
|
||||
cmd.arg("--target");
|
||||
cmd.arg(sess.target.llvm_target.as_ref());
|
||||
cmd.arg("--target-cpu");
|
||||
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||
cmd.link_args(&[
|
||||
"--target",
|
||||
sess.target.llvm_target.as_ref(),
|
||||
"--target-cpu",
|
||||
&codegen_results.crate_info.target_cpu,
|
||||
]);
|
||||
} else if flavor == LinkerFlavor::Ptx {
|
||||
cmd.arg("--fallback-arch");
|
||||
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||
cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]);
|
||||
} else if flavor == LinkerFlavor::Bpf {
|
||||
cmd.arg("--cpu");
|
||||
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||
cmd.link_args(&["--cpu", &codegen_results.crate_info.target_cpu]);
|
||||
if let Some(feat) = [sess.opts.cg.target_feature.as_str(), &sess.target.options.features]
|
||||
.into_iter()
|
||||
.find(|feat| !feat.is_empty())
|
||||
{
|
||||
cmd.arg("--cpu-features");
|
||||
cmd.arg(feat);
|
||||
cmd.link_args(&["--cpu-features", feat]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2618,7 +2618,11 @@ fn add_native_libs_from_crate(
|
|||
NativeLibKind::WasmImportModule => {}
|
||||
NativeLibKind::LinkArg => {
|
||||
if link_static {
|
||||
cmd.linker_arg(OsStr::new(name), verbatim);
|
||||
if verbatim {
|
||||
cmd.verbatim_arg(name);
|
||||
} else {
|
||||
cmd.link_arg(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3012,10 +3016,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
|||
// This is admittedly a bit strange, as on most targets
|
||||
// `-isysroot` only applies to include header files, but on Apple
|
||||
// targets this also applies to libraries and frameworks.
|
||||
cmd.args(&["-isysroot", &sdk_root]);
|
||||
cmd.cc_args(&["-isysroot", &sdk_root]);
|
||||
}
|
||||
LinkerFlavor::Darwin(Cc::No, _) => {
|
||||
cmd.args(&["-syslibroot", &sdk_root]);
|
||||
cmd.link_args(&["-syslibroot", &sdk_root]);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
@ -3026,8 +3030,9 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
|||
// search path.
|
||||
|
||||
// The flags are called `-L` and `-F` both in Clang, ld64 and ldd.
|
||||
cmd.arg(format!("-L{sdk_root}/System/iOSSupport/usr/lib"));
|
||||
cmd.arg(format!("-F{sdk_root}/System/iOSSupport/System/Library/Frameworks"));
|
||||
let sdk_root = Path::new(&sdk_root);
|
||||
cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
|
||||
cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3142,7 +3147,7 @@ fn add_lld_args(
|
|||
for path in sess.get_tools_search_paths(false) {
|
||||
let linker_path = path.join("gcc-ld");
|
||||
linker_path_exists |= linker_path.exists();
|
||||
cmd.arg({
|
||||
cmd.cc_arg({
|
||||
let mut arg = OsString::from("-B");
|
||||
arg.push(linker_path);
|
||||
arg
|
||||
|
|
@ -3162,7 +3167,7 @@ fn add_lld_args(
|
|||
// is to use LLD but the `wasm32-wasip2` target relies on a wrapper around
|
||||
// this, `wasm-component-ld`, which is overridden if this option is passed.
|
||||
if !sess.target.is_like_wasm {
|
||||
cmd.arg("-fuse-ld=lld");
|
||||
cmd.cc_arg("-fuse-ld=lld");
|
||||
}
|
||||
|
||||
if !flavor.is_gnu() {
|
||||
|
|
@ -3186,7 +3191,7 @@ fn add_lld_args(
|
|||
// targeting a different linker flavor on macOS, and that's also always
|
||||
// the case when targeting WASM.
|
||||
if sess.target.linker_flavor != sess.host.linker_flavor {
|
||||
cmd.arg(format!("--target={}", sess.target.llvm_target));
|
||||
cmd.cc_arg(format!("--target={}", sess.target.llvm_target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,16 +9,10 @@ pub struct RPathConfig<'a> {
|
|||
pub libs: &'a [&'a Path],
|
||||
pub out_filename: PathBuf,
|
||||
pub is_like_osx: bool,
|
||||
pub has_rpath: bool,
|
||||
pub linker_is_gnu: bool,
|
||||
}
|
||||
|
||||
pub fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec<OsString> {
|
||||
// No rpath on windows
|
||||
if !config.has_rpath {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
debug!("preparing the RPATH!");
|
||||
|
||||
let rpaths = get_rpaths(config);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ fn test_rpath_relative() {
|
|||
if cfg!(target_os = "macos") {
|
||||
let config = &mut RPathConfig {
|
||||
libs: &[],
|
||||
has_rpath: true,
|
||||
is_like_osx: true,
|
||||
linker_is_gnu: false,
|
||||
out_filename: PathBuf::from("bin/rustc"),
|
||||
|
|
@ -48,7 +47,6 @@ fn test_rpath_relative() {
|
|||
let config = &mut RPathConfig {
|
||||
libs: &[],
|
||||
out_filename: PathBuf::from("bin/rustc"),
|
||||
has_rpath: true,
|
||||
is_like_osx: false,
|
||||
linker_is_gnu: true,
|
||||
};
|
||||
|
|
@ -62,7 +60,6 @@ fn test_rpath_relative_issue_119571() {
|
|||
let config = &mut RPathConfig {
|
||||
libs: &[],
|
||||
out_filename: PathBuf::from("rustc"),
|
||||
has_rpath: true,
|
||||
is_like_osx: false,
|
||||
linker_is_gnu: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
|||
let align = cx.data_layout().pointer_align.abi;
|
||||
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
|
||||
|
||||
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
|
||||
cx.create_vtable_debuginfo(ty, trait_ref, vtable);
|
||||
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
|
||||
vtable
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// with #[rustc_inherit_overflow_checks] and inlined from
|
||||
// another crate (mostly core::num generic/#[inline] fns),
|
||||
// while the current crate doesn't use overflow checks.
|
||||
if !bx.cx().check_overflow() && msg.is_optional_overflow_check() {
|
||||
if !bx.sess().overflow_checks() && msg.is_optional_overflow_check() {
|
||||
const_cond = Some(expected);
|
||||
}
|
||||
|
||||
|
|
@ -751,7 +751,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&mut self,
|
||||
helper: &TerminatorCodegenHelper<'tcx>,
|
||||
bx: &mut Bx,
|
||||
intrinsic: Option<ty::IntrinsicDef>,
|
||||
intrinsic: ty::IntrinsicDef,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
source_info: mir::SourceInfo,
|
||||
target: Option<mir::BasicBlock>,
|
||||
|
|
@ -761,8 +761,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// Emit a panic or a no-op for `assert_*` intrinsics.
|
||||
// These are intrinsics that compile to panics so that we can get a message
|
||||
// which mentions the offending type, even from a const context.
|
||||
let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
|
||||
if let Some(requirement) = panic_intrinsic {
|
||||
if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
|
||||
let ty = instance.unwrap().args.type_at(0);
|
||||
|
||||
let do_panic = !bx
|
||||
|
|
@ -869,12 +868,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let sig = callee.layout.ty.fn_sig(bx.tcx());
|
||||
let abi = sig.abi();
|
||||
|
||||
// Handle intrinsics old codegen wants Expr's for, ourselves.
|
||||
let intrinsic = match def {
|
||||
Some(ty::InstanceKind::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
||||
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
|
||||
let op_ty = op_arg.node.ty(self.mir, bx.tcx());
|
||||
|
|
@ -886,50 +879,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
None => bx.fn_abi_of_fn_ptr(sig, extra_args),
|
||||
};
|
||||
|
||||
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
||||
&helper,
|
||||
bx,
|
||||
intrinsic,
|
||||
instance,
|
||||
source_info,
|
||||
target,
|
||||
unwind,
|
||||
mergeable_succ,
|
||||
) {
|
||||
return merging_succ;
|
||||
}
|
||||
|
||||
// The arguments we'll be passing. Plus one to account for outptr, if used.
|
||||
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
|
||||
|
||||
if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
|
||||
return if let Some(target) = target {
|
||||
let location =
|
||||
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
let ret_dest = self.make_return_dest(
|
||||
let instance = match def {
|
||||
Some(ty::InstanceKind::Intrinsic(def_id)) => {
|
||||
let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
|
||||
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
||||
&helper,
|
||||
bx,
|
||||
destination,
|
||||
&fn_abi.ret,
|
||||
&mut llargs,
|
||||
intrinsic,
|
||||
Some(target),
|
||||
);
|
||||
assert_eq!(llargs, []);
|
||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||
location.val.store(bx, tmp);
|
||||
instance,
|
||||
source_info,
|
||||
target,
|
||||
unwind,
|
||||
mergeable_succ,
|
||||
) {
|
||||
return merging_succ;
|
||||
}
|
||||
self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
|
||||
helper.funclet_br(self, bx, target, mergeable_succ)
|
||||
} else {
|
||||
MergingSucc::False
|
||||
};
|
||||
}
|
||||
|
||||
let instance = match intrinsic {
|
||||
None => instance,
|
||||
Some(intrinsic) => {
|
||||
let mut llargs = Vec::with_capacity(1);
|
||||
let ret_dest = self.make_return_dest(
|
||||
bx,
|
||||
|
|
@ -971,6 +939,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) {
|
||||
let location = self
|
||||
.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
||||
|
||||
assert_eq!(llargs, []);
|
||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||
location.val.store(bx, tmp);
|
||||
}
|
||||
self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
|
||||
return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
|
||||
}
|
||||
|
||||
let instance = *instance.as_ref().unwrap();
|
||||
match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
|
||||
Ok(()) => {
|
||||
|
|
@ -997,6 +977,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => instance,
|
||||
};
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ use rustc_session::{
|
|||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub trait BackendTypes {
|
||||
type Value: CodegenObject;
|
||||
type Function: CodegenObject;
|
||||
|
|
@ -62,7 +60,7 @@ pub trait CodegenBackend {
|
|||
fn locale_resource(&self) -> &'static str;
|
||||
|
||||
fn init(&self, _sess: &Session) {}
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut dyn PrintBackendInfo, _sess: &Session) {}
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
|
||||
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
|
||||
vec![]
|
||||
}
|
||||
|
|
@ -150,19 +148,3 @@ pub trait ExtraBackendMethods:
|
|||
std::thread::Builder::new().name(name).spawn(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PrintBackendInfo {
|
||||
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>);
|
||||
}
|
||||
|
||||
impl PrintBackendInfo for String {
|
||||
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||
fmt::Write::write_fmt(self, args).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn PrintBackendInfo + '_ {
|
||||
pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||
self.infallible_write_fmt(args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,5 @@ pub trait ConstMethods<'tcx>: BackendTypes {
|
|||
|
||||
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
|
||||
|
||||
fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
|
||||
fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,13 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
|||
fn vtables(
|
||||
&self,
|
||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
|
||||
fn check_overflow(&self) -> bool;
|
||||
fn apply_vcall_visibility_metadata(
|
||||
&self,
|
||||
_ty: Ty<'tcx>,
|
||||
_poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
_vtable: Self::Value,
|
||||
) {
|
||||
}
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
|
||||
fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value;
|
||||
fn eh_personality(&self) -> Self::Value;
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@ mod write;
|
|||
|
||||
pub use self::abi::AbiBuilderMethods;
|
||||
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
|
||||
pub use self::backend::{
|
||||
Backend, BackendTypes, CodegenBackend, ExtraBackendMethods, PrintBackendInfo,
|
||||
};
|
||||
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||
pub use self::consts::ConstMethods;
|
||||
pub use self::coverageinfo::CoverageInfoBuilderMethods;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use rustc_target::abi::{AddressSpace, Float, Integer};
|
|||
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
||||
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
||||
pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
||||
fn type_i1(&self) -> Self::Type;
|
||||
fn type_i8(&self) -> Self::Type;
|
||||
fn type_i16(&self) -> Self::Type;
|
||||
fn type_i32(&self) -> Self::Type;
|
||||
|
|
@ -27,7 +26,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
|||
|
||||
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
|
||||
fn type_kind(&self, ty: Self::Type) -> TypeKind;
|
||||
fn type_ptr(&self) -> Self::Type;
|
||||
fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type;
|
||||
|
|
@ -115,8 +113,8 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
|
|||
/// The backend type used for a rust type when it's in an SSA register.
|
||||
///
|
||||
/// For nearly all types this is the same as the [`Self::backend_type`], however
|
||||
/// `bool` (and other `0`-or-`1` values) are kept as [`BaseTypeMethods::type_i1`]
|
||||
/// in registers but as [`BaseTypeMethods::type_i8`] in memory.
|
||||
/// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as
|
||||
/// [`BaseTypeMethods::type_i8`] in memory.
|
||||
///
|
||||
/// Converting values between the two different backend types is done using
|
||||
/// [`from_immediate`](super::BuilderMethods::from_immediate) and
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
|||
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
|
||||
hir::Constness::Const
|
||||
}
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => tcx
|
||||
.generics_of(def_id)
|
||||
.host_effect_index
|
||||
.map_or(hir::Constness::NotConst, |_| hir::Constness::Const),
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
|
||||
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
|
||||
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
|
||||
// foreign items cannot be evaluated at compile-time.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
|
||||
use rustc_middle::mir::CastKind;
|
||||
|
|
@ -187,10 +187,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty)
|
||||
};
|
||||
let val = match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F16 => self.cast_from_float(src.to_scalar().to_f16()?, cast_to.ty),
|
||||
FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
|
||||
FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
FloatTy::F128 => self.cast_from_float(src.to_scalar().to_f128()?, cast_to.ty),
|
||||
};
|
||||
Ok(ImmTy::from_scalar(val, cast_to))
|
||||
}
|
||||
|
|
@ -296,18 +296,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
Float(fty) if signed => {
|
||||
let v = v as i128;
|
||||
match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F16 => Scalar::from_f16(Half::from_i128(v).value),
|
||||
FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value),
|
||||
FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
FloatTy::F128 => Scalar::from_f128(Quad::from_i128(v).value),
|
||||
}
|
||||
}
|
||||
// unsigned int -> float
|
||||
Float(fty) => match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F16 => Scalar::from_f16(Half::from_u128(v).value),
|
||||
FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value),
|
||||
FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
FloatTy::F128 => Scalar::from_f128(Quad::from_u128(v).value),
|
||||
},
|
||||
|
||||
// u8 -> char
|
||||
|
|
@ -321,7 +321,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
/// Low-level cast helper function. Converts an apfloat `f` into int or float types.
|
||||
fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::Provenance>
|
||||
where
|
||||
F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>,
|
||||
F: Float
|
||||
+ Into<Scalar<M::Provenance>>
|
||||
+ FloatConvert<Half>
|
||||
+ FloatConvert<Single>
|
||||
+ FloatConvert<Double>
|
||||
+ FloatConvert<Quad>,
|
||||
{
|
||||
use rustc_type_ir::TyKind::*;
|
||||
|
||||
|
|
@ -358,10 +363,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
// float -> float
|
||||
Float(fty) => match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)),
|
||||
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
|
||||
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
FloatTy::F128 => {
|
||||
Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value))
|
||||
}
|
||||
},
|
||||
// That's it.
|
||||
_ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ libc = "0.2"
|
|||
memmap2 = "0.2.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[target.'cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))'.dependencies]
|
||||
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
|
||||
portable-atomic = "1.5.1"
|
||||
|
||||
[features]
|
||||
|
|
|
|||
|
|
@ -147,14 +147,13 @@ cfg_match! {
|
|||
[crate::owned_slice::OwnedSlice]
|
||||
);
|
||||
|
||||
// MIPS, PowerPC and SPARC platforms with 32-bit pointers do not
|
||||
// have AtomicU64 type.
|
||||
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc", target_arch = "sparc")))]
|
||||
// Use portable AtomicU64 for targets without native 64-bit atomics
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
already_sync!(
|
||||
[std::sync::atomic::AtomicU64]
|
||||
);
|
||||
|
||||
#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))]
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
already_sync!(
|
||||
[portable_atomic::AtomicU64]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -270,12 +270,11 @@ cfg_match! {
|
|||
|
||||
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32};
|
||||
|
||||
// MIPS, PowerPC and SPARC platforms with 32-bit pointers do not
|
||||
// have AtomicU64 type.
|
||||
#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc")))]
|
||||
// Use portable AtomicU64 for targets without native 64-bit atomics
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
pub use std::sync::atomic::AtomicU64;
|
||||
|
||||
#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))]
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
pub use portable_atomic::AtomicU64;
|
||||
|
||||
pub use std::sync::Arc as Lrc;
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
|
|||
// would be bad.
|
||||
impl<G> !Clone for Diag<'_, G> {}
|
||||
|
||||
rustc_data_structures::static_assert_size!(Diag<'_, ()>, 2 * std::mem::size_of::<usize>());
|
||||
rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * std::mem::size_of::<usize>());
|
||||
|
||||
impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
|
||||
type Target = DiagInner;
|
||||
|
|
@ -582,6 +582,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
Self::new_diagnostic(dcx, DiagInner::new(level, message))
|
||||
}
|
||||
|
||||
/// Allow moving diagnostics between different error tainting contexts
|
||||
pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
|
||||
Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Creates a new `Diag` with an already constructed diagnostic.
|
||||
#[track_caller]
|
||||
pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ use rustc_span::source_map::SourceMap;
|
|||
use rustc_span::{Loc, Span, DUMMY_SP};
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::error::Report;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
|
@ -98,9 +99,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
|||
|
||||
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
|
||||
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
|
||||
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
|
||||
pub enum SuggestionStyle {
|
||||
|
|
@ -417,6 +418,9 @@ pub struct DiagCtxt {
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct DiagCtxtHandle<'a> {
|
||||
dcx: &'a DiagCtxt,
|
||||
/// Some contexts create `DiagCtxtHandle` with this field set, and thus all
|
||||
/// errors emitted with it will automatically taint when emitting errors.
|
||||
tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
|
||||
}
|
||||
|
||||
impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
|
||||
|
|
@ -752,7 +756,17 @@ impl DiagCtxt {
|
|||
}
|
||||
|
||||
pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
|
||||
DiagCtxtHandle { dcx: self }
|
||||
DiagCtxtHandle { dcx: self, tainted_with_errors: None }
|
||||
}
|
||||
|
||||
/// Link this to a taintable context so that emitting errors will automatically set
|
||||
/// the `Option<ErrorGuaranteed>` instead of having to do that manually at every error
|
||||
/// emission site.
|
||||
pub fn taintable_handle<'a>(
|
||||
&'a self,
|
||||
tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
|
||||
) -> DiagCtxtHandle<'a> {
|
||||
DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -795,7 +809,9 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
// can be used to create a backtrace at the stashing site insted of whenever the
|
||||
// diagnostic context is dropped and thus delayed bugs are emitted.
|
||||
Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))),
|
||||
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
|
||||
DelayedBug => {
|
||||
return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
|
||||
}
|
||||
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
|
||||
| Expect(_) => None,
|
||||
};
|
||||
|
|
@ -947,16 +963,19 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
(0, _) => {
|
||||
// Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a
|
||||
// configuration like `--cap-lints allow --force-warn bare_trait_objects`.
|
||||
inner.emit_diagnostic(DiagInner::new(
|
||||
ForceWarning(None),
|
||||
DiagMessage::Str(warnings),
|
||||
));
|
||||
inner.emit_diagnostic(
|
||||
DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)),
|
||||
None,
|
||||
);
|
||||
}
|
||||
(_, 0) => {
|
||||
inner.emit_diagnostic(DiagInner::new(Error, errors));
|
||||
inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
|
||||
}
|
||||
(_, _) => {
|
||||
inner.emit_diagnostic(DiagInner::new(Error, format!("{errors}; {warnings}")));
|
||||
inner.emit_diagnostic(
|
||||
DiagInner::new(Error, format!("{errors}; {warnings}")),
|
||||
self.tainted_with_errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -987,14 +1006,14 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
"For more information about an error, try `rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
);
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1));
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2));
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
|
||||
} else {
|
||||
let msg = format!(
|
||||
"For more information about this error, try `rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
);
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg));
|
||||
inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1020,7 +1039,7 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
}
|
||||
|
||||
pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
||||
self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
|
||||
}
|
||||
|
||||
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
||||
|
|
@ -1080,7 +1099,7 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
// Here the diagnostic is given back to `emit_diagnostic` where it was first
|
||||
// intercepted. Now it should be processed as usual, since the unstable expectation
|
||||
// id is now stable.
|
||||
inner.emit_diagnostic(diag);
|
||||
inner.emit_diagnostic(diag, self.tainted_with_errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1430,13 +1449,17 @@ impl DiagCtxtInner {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
guar = guar.or(self.emit_diagnostic(diag));
|
||||
guar = guar.or(self.emit_diagnostic(diag, None));
|
||||
}
|
||||
guar
|
||||
}
|
||||
|
||||
// Return value is only `Some` if the level is `Error` or `DelayedBug`.
|
||||
fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
|
||||
fn emit_diagnostic(
|
||||
&mut self,
|
||||
mut diagnostic: DiagInner,
|
||||
taint: Option<&Cell<Option<ErrorGuaranteed>>>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
match diagnostic.level {
|
||||
Expect(expect_id) | ForceWarning(Some(expect_id)) => {
|
||||
// The `LintExpectationId` can be stable or unstable depending on when it was
|
||||
|
|
@ -1609,6 +1632,9 @@ impl DiagCtxtInner {
|
|||
if is_lint {
|
||||
self.lint_err_guars.push(guar);
|
||||
} else {
|
||||
if let Some(taint) = taint {
|
||||
taint.set(Some(guar));
|
||||
}
|
||||
self.err_guars.push(guar);
|
||||
}
|
||||
self.panic_if_treat_err_as_bug();
|
||||
|
|
@ -1718,8 +1744,8 @@ impl DiagCtxtInner {
|
|||
// `-Ztreat-err-as-bug`, which we don't want.
|
||||
let note1 = "no errors encountered even though delayed bugs were created";
|
||||
let note2 = "those delayed bugs will now be shown as internal compiler errors";
|
||||
self.emit_diagnostic(DiagInner::new(Note, note1));
|
||||
self.emit_diagnostic(DiagInner::new(Note, note2));
|
||||
self.emit_diagnostic(DiagInner::new(Note, note1), None);
|
||||
self.emit_diagnostic(DiagInner::new(Note, note2), None);
|
||||
|
||||
for bug in bugs {
|
||||
if let Some(out) = &mut out {
|
||||
|
|
@ -1752,7 +1778,7 @@ impl DiagCtxtInner {
|
|||
}
|
||||
bug.level = Bug;
|
||||
|
||||
self.emit_diagnostic(bug);
|
||||
self.emit_diagnostic(bug, None);
|
||||
}
|
||||
|
||||
// Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.
|
||||
|
|
|
|||
|
|
@ -833,6 +833,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_runtime, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::No, INTERNAL_UNSTABLE
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes, Layout related:
|
||||
|
|
@ -1113,6 +1117,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
TEST, rustc_dump_predicates, Normal, template!(Word),
|
||||
WarnFollowing, EncodeCrossCrate::No
|
||||
),
|
||||
rustc_attr!(
|
||||
TEST, rustc_dump_def_parents, Normal, template!(Word),
|
||||
WarnFollowing, EncodeCrossCrate::No
|
||||
),
|
||||
rustc_attr!(
|
||||
TEST, rustc_object_lifetime_default, Normal, template!(Word),
|
||||
WarnFollowing, EncodeCrossCrate::No
|
||||
|
|
|
|||
|
|
@ -526,6 +526,7 @@ pub enum GenericParamKind<'hir> {
|
|||
/// Optional default value for the const generic param
|
||||
default: Option<&'hir AnonConst>,
|
||||
is_host_effect: bool,
|
||||
synthetic: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -3364,6 +3365,7 @@ pub enum ItemKind<'hir> {
|
|||
/// Refer to [`ImplItem`] for an associated item within an impl block.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Impl<'hir> {
|
||||
pub constness: Constness,
|
||||
pub safety: Safety,
|
||||
pub polarity: ImplPolarity,
|
||||
pub defaultness: Defaultness,
|
||||
|
|
|
|||
|
|
@ -543,6 +543,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
|||
try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id()));
|
||||
}
|
||||
ItemKind::Impl(Impl {
|
||||
constness: _,
|
||||
safety: _,
|
||||
defaultness: _,
|
||||
polarity: _,
|
||||
|
|
@ -915,7 +916,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
|
|||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
|
||||
GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => {
|
||||
GenericParamKind::Const { ref ty, ref default, is_host_effect: _, synthetic: _ } => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
if let Some(ref default) = default {
|
||||
try_visit!(visitor.visit_const_param_default(param.hir_id, default));
|
||||
|
|
|
|||
|
|
@ -393,6 +393,14 @@ language_item_table! {
|
|||
|
||||
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
||||
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
||||
|
||||
EffectsRuntime, sym::EffectsRuntime, effects_runtime, Target::Struct, GenericRequirement::None;
|
||||
EffectsNoRuntime, sym::EffectsNoRuntime, effects_no_runtime, Target::Struct, GenericRequirement::None;
|
||||
EffectsMaybe, sym::EffectsMaybe, effects_maybe, Target::Struct, GenericRequirement::None;
|
||||
EffectsIntersection, sym::EffectsIntersection, effects_intersection, Target::Trait, GenericRequirement::None;
|
||||
EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None;
|
||||
EffectsCompat, sym::EffectsCompat, effects_compat, Target::Trait, GenericRequirement::Exact(1);
|
||||
EffectsTyCompat, sym::EffectsTyCompat, effects_ty_compat, Target::Trait, GenericRequirement::Exact(1);
|
||||
}
|
||||
|
||||
pub enum GenericRequirement {
|
||||
|
|
|
|||
|
|
@ -120,6 +120,10 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
|
|||
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
|
||||
.label = parameter captured again here
|
||||
|
||||
hir_analysis_effects_without_next_solver = using `#![feature(effects)]` without enabling next trait solver globally
|
||||
.note = the next trait solver must be enabled globally for the effects feature to work correctly
|
||||
.help = use `-Znext-solver` to enable
|
||||
|
||||
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
|
||||
.note = impl is a specialization of this impl
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
|
||||
//! [`rustc_middle::ty`] form.
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
/// Collects together a list of type bounds. These lists of bounds occur in many places
|
||||
/// in Rust's syntax:
|
||||
|
|
@ -24,6 +28,7 @@ use rustc_span::Span;
|
|||
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
||||
pub struct Bounds<'tcx> {
|
||||
clauses: Vec<(ty::Clause<'tcx>, Span)>,
|
||||
effects_min_tys: FxIndexMap<Ty<'tcx>, Span>,
|
||||
}
|
||||
|
||||
impl<'tcx> Bounds<'tcx> {
|
||||
|
|
@ -40,12 +45,14 @@ impl<'tcx> Bounds<'tcx> {
|
|||
pub fn push_trait_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
defining_def_id: DefId,
|
||||
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::PredicatePolarity,
|
||||
constness: ty::BoundConstness,
|
||||
) {
|
||||
let clause = (
|
||||
trait_ref
|
||||
bound_trait_ref
|
||||
.map_bound(|trait_ref| {
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
||||
})
|
||||
|
|
@ -53,11 +60,98 @@ impl<'tcx> Bounds<'tcx> {
|
|||
span,
|
||||
);
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
|
||||
if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) {
|
||||
self.clauses.insert(0, clause);
|
||||
} else {
|
||||
self.clauses.push(clause);
|
||||
}
|
||||
|
||||
if !tcx.features().effects {
|
||||
return;
|
||||
}
|
||||
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
|
||||
// associated type of `<T as Tr>` and make sure that the effect is compatible.
|
||||
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
|
||||
// FIXME(effects): revisit the correctness of this
|
||||
(_, ty::BoundConstness::Const) => tcx.consts.false_,
|
||||
// body owners that can have trait bounds
|
||||
(DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => {
|
||||
tcx.expected_host_effect_param_for_body(defining_def_id)
|
||||
}
|
||||
|
||||
(_, ty::BoundConstness::NotConst) => {
|
||||
if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) {
|
||||
return;
|
||||
}
|
||||
tcx.consts.true_
|
||||
}
|
||||
|
||||
(
|
||||
DefKind::Trait | DefKind::Impl { of_trait: true },
|
||||
ty::BoundConstness::ConstIfConst,
|
||||
) => {
|
||||
// this is either a where clause on an impl/trait header or on a trait.
|
||||
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||
return;
|
||||
};
|
||||
|
||||
let ty = bound_trait_ref
|
||||
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
|
||||
|
||||
// When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
|
||||
// binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
|
||||
// the `Min` associated type properly (which doesn't allow using `for<>`)
|
||||
// This should work for any bound variables as long as they don't have any
|
||||
// bounds e.g. `for<T: Trait>`.
|
||||
// FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
|
||||
let ty = tcx.replace_bound_vars_uncached(
|
||||
ty,
|
||||
FnMutDelegate {
|
||||
regions: &mut |_| tcx.lifetimes.re_static,
|
||||
types: &mut |_| tcx.types.unit,
|
||||
consts: &mut |_| unimplemented!("`~const` does not support const binders"),
|
||||
},
|
||||
);
|
||||
|
||||
self.effects_min_tys.insert(ty, span);
|
||||
return;
|
||||
}
|
||||
// for
|
||||
// ```
|
||||
// trait Foo { type Bar: ~const Trait }
|
||||
// ```
|
||||
// ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
|
||||
//
|
||||
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
|
||||
// that uses a `Bar` that implements `Trait` with `Maybe` effects.
|
||||
(DefKind::AssocTy, ty::BoundConstness::ConstIfConst) => {
|
||||
// FIXME(effects): implement this
|
||||
return;
|
||||
}
|
||||
// probably illegal in this position.
|
||||
(_, ty::BoundConstness::ConstIfConst) => {
|
||||
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
|
||||
return;
|
||||
}
|
||||
};
|
||||
// create a new projection type `<T as Tr>::Effects`
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"`~const` trait bound has no effect assoc yet no errors encountered?",
|
||||
);
|
||||
return;
|
||||
};
|
||||
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
|
||||
// make `<T as Tr>::Effects: Compat<runtime>`
|
||||
let new_trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::EffectsCompat, Some(span)),
|
||||
[ty::GenericArg::from(self_ty), compat_val.into()],
|
||||
);
|
||||
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
|
||||
}
|
||||
|
||||
pub fn push_projection_bound(
|
||||
|
|
@ -79,7 +173,15 @@ impl<'tcx> Bounds<'tcx> {
|
|||
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
|
||||
}
|
||||
|
||||
pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
|
||||
pub fn clauses(
|
||||
&self,
|
||||
// FIXME(effects): remove tcx
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
|
||||
self.clauses.iter().cloned()
|
||||
}
|
||||
|
||||
pub fn effects_min_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
|
||||
self.effects_min_tys.keys().copied()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -879,7 +879,8 @@ pub(super) fn check_specialization_validity<'tcx>(
|
|||
let result = opt_result.unwrap_or(Ok(()));
|
||||
|
||||
if let Err(parent_impl) = result {
|
||||
if !tcx.is_impl_trait_in_trait(impl_item) {
|
||||
// FIXME(effects) the associated type from effects could be specialized
|
||||
if !tcx.is_impl_trait_in_trait(impl_item) && !tcx.is_effects_desugared_assoc_ty(impl_item) {
|
||||
report_forbidden_specialization(tcx, impl_item, parent_impl);
|
||||
} else {
|
||||
tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
|
||||
|
|
|
|||
|
|
@ -1985,10 +1985,10 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
|
||||
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
||||
// associated type.
|
||||
let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
|
||||
// A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,
|
||||
// which we currently use to get the span for an impl's associated type. Instead, for these,
|
||||
// use the def_span for the synthesized associated type.
|
||||
let impl_ty_span = if impl_ty.is_impl_trait_in_trait() || impl_ty.is_effects_desugaring {
|
||||
tcx.def_span(impl_ty_def_id)
|
||||
} else {
|
||||
match tcx.hir_node_by_def_id(impl_ty_def_id) {
|
||||
|
|
|
|||
|
|
@ -913,7 +913,12 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
||||
|
||||
// Const parameters are well formed if their type is structural match.
|
||||
hir::GenericParamKind::Const { ty: hir_ty, default: _, is_host_effect: _ } => {
|
||||
hir::GenericParamKind::Const {
|
||||
ty: hir_ty,
|
||||
default: _,
|
||||
is_host_effect: _,
|
||||
synthetic: _,
|
||||
} => {
|
||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
|
||||
if tcx.features().adt_const_params {
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ pub fn provide(providers: &mut Providers) {
|
|||
predicates_of: predicates_of::predicates_of,
|
||||
predicates_defined_on,
|
||||
explicit_predicates_of: predicates_of::explicit_predicates_of,
|
||||
super_predicates_of: predicates_of::super_predicates_of,
|
||||
implied_predicates_of: predicates_of::implied_predicates_of,
|
||||
super_predicates_that_define_assoc_item:
|
||||
predicates_of::super_predicates_that_define_assoc_item,
|
||||
explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
|
||||
explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
|
||||
explicit_supertraits_containing_assoc_item:
|
||||
predicates_of::explicit_supertraits_containing_assoc_item,
|
||||
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
|
||||
type_param_predicates: predicates_of::type_param_predicates,
|
||||
trait_def,
|
||||
|
|
@ -691,14 +691,14 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
hir::ItemKind::Trait(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().trait_def(def_id);
|
||||
tcx.at(it.span).super_predicates_of(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().associated_items(def_id);
|
||||
}
|
||||
hir::ItemKind::TraitAlias(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.at(it.span).implied_predicates_of(def_id);
|
||||
tcx.at(it.span).super_predicates_of(def_id);
|
||||
tcx.at(it.span).explicit_implied_predicates_of(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
}
|
||||
hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => {
|
||||
|
|
@ -1459,8 +1459,25 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||
Some(ty) => {
|
||||
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||
// This is a heuristic approach. If the scope has region paramters,
|
||||
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
|
||||
// otherwise to `ReStatic`.
|
||||
let has_region_params = generics.params.iter().any(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
|
||||
ty::ReErased => tcx.lifetimes.re_static,
|
||||
ty::ReErased => {
|
||||
if has_region_params {
|
||||
ty::Region::new_error_with_message(
|
||||
tcx,
|
||||
DUMMY_SP,
|
||||
"erased region is not allowed here in return type",
|
||||
)
|
||||
} else {
|
||||
tcx.lifetimes.re_static
|
||||
}
|
||||
}
|
||||
_ => r,
|
||||
});
|
||||
|
||||
|
|
@ -1638,44 +1655,19 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
|||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let item = tcx.hir().expect_item(def_id);
|
||||
let impl_ = item.expect_impl();
|
||||
impl_
|
||||
.of_trait
|
||||
.as_ref()
|
||||
.map(|hir_trait_ref| {
|
||||
let self_ty = tcx.type_of(def_id).instantiate_identity();
|
||||
impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
||||
let selfty = tcx.type_of(def_id).instantiate_identity();
|
||||
|
||||
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
|
||||
tcx,
|
||||
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
|
||||
hir_trait_ref,
|
||||
) {
|
||||
// we have a const impl, but for a trait without `#[const_trait]`, so
|
||||
// without the host param. If we continue with the HIR trait ref, we get
|
||||
// ICEs for generic arg count mismatch. We do a little HIR editing to
|
||||
// make HIR ty lowering happy.
|
||||
let mut path_segments = hir_trait_ref.path.segments.to_vec();
|
||||
let last_segment = path_segments.len() - 1;
|
||||
let mut args = *path_segments[last_segment].args();
|
||||
let last_arg = args.args.len() - 1;
|
||||
assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects));
|
||||
args.args = &args.args[..args.args.len() - 1];
|
||||
path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args));
|
||||
let path = hir::Path {
|
||||
span: hir_trait_ref.path.span,
|
||||
res: hir_trait_ref.path.res,
|
||||
segments: tcx.hir_arena.alloc_slice(&path_segments),
|
||||
};
|
||||
let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: hir_trait_ref.hir_ref_id });
|
||||
icx.lowerer().lower_impl_trait_ref(trait_ref, self_ty)
|
||||
} else {
|
||||
icx.lowerer().lower_impl_trait_ref(hir_trait_ref, self_ty)
|
||||
};
|
||||
ty::ImplTraitHeader {
|
||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||
safety: impl_.safety,
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
|
||||
}
|
||||
})
|
||||
check_impl_constness(tcx, tcx.is_const_trait_impl_raw(def_id.to_def_id()), ast_trait_ref);
|
||||
|
||||
let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
|
||||
|
||||
ty::ImplTraitHeader {
|
||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||
safety: impl_.safety,
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn check_impl_constness(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::sym;
|
||||
|
||||
|
|
@ -41,3 +43,49 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
||||
for did in tcx.hir().body_owners() {
|
||||
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
|
||||
struct AnonConstFinder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
anon_consts: Vec<LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
|
||||
type NestedFilter = OnlyBodies;
|
||||
|
||||
fn nested_visit_map(&mut self) -> Self::Map {
|
||||
self.tcx.hir()
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) {
|
||||
self.anon_consts.push(c.def_id);
|
||||
intravisit::walk_anon_const(self, c)
|
||||
}
|
||||
}
|
||||
|
||||
// Look for any anon consts inside of this body owner as there is no way to apply
|
||||
// the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
|
||||
// to see what its def parent is.
|
||||
let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
|
||||
intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value);
|
||||
|
||||
for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
|
||||
let span = tcx.def_span(did);
|
||||
|
||||
let mut diag = tcx.dcx().struct_span_err(
|
||||
span,
|
||||
format!("{}: {did:?}", sym::rustc_dump_def_parents.as_str()),
|
||||
);
|
||||
|
||||
let mut current_did = did.to_def_id();
|
||||
while let Some(parent_did) = tcx.opt_parent(current_did) {
|
||||
current_did = parent_did;
|
||||
diag.span_note(tcx.def_span(parent_did), format!("{parent_did:?}"));
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
kind,
|
||||
})
|
||||
}
|
||||
GenericParamKind::Const { ty: _, default, is_host_effect } => {
|
||||
GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => {
|
||||
if !matches!(allow_defaults, Defaults::Allowed)
|
||||
&& default.is_some()
|
||||
// `host` effect params are allowed to have defaults.
|
||||
|
|
@ -388,6 +388,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
kind: ty::GenericParamDefKind::Const {
|
||||
has_default: default.is_some(),
|
||||
is_host_effect,
|
||||
synthetic,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -541,7 +542,8 @@ struct AnonConstInParamTyDetector {
|
|||
|
||||
impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
|
||||
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
|
||||
if let GenericParamKind::Const { ty, default: _, is_host_effect: _ } = p.kind {
|
||||
if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
|
||||
{
|
||||
let prev = self.in_param_ty;
|
||||
self.in_param_ty = true;
|
||||
self.visit_ty(ty);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFold
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::Upcast;
|
||||
|
||||
/// For associated types we include both bounds written on the type
|
||||
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
|
||||
|
|
@ -46,7 +47,7 @@ fn associated_type_bounds<'tcx>(
|
|||
}
|
||||
});
|
||||
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses(tcx).chain(bounds_from_parent));
|
||||
debug!(
|
||||
"associated_type_bounds({}) = {:?}",
|
||||
tcx.def_path_str(assoc_item_def_id.to_def_id()),
|
||||
|
|
@ -75,7 +76,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
|
||||
debug!(?bounds);
|
||||
|
||||
tcx.arena.alloc_from_iter(bounds.clauses())
|
||||
tcx.arena.alloc_from_iter(bounds.clauses(tcx))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +125,32 @@ pub(super) fn explicit_item_bounds_with_filter(
|
|||
None => {}
|
||||
}
|
||||
|
||||
if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) {
|
||||
let mut predicates = Vec::new();
|
||||
|
||||
let parent = tcx.local_parent(def_id);
|
||||
|
||||
let preds = tcx.explicit_predicates_of(parent);
|
||||
|
||||
if let ty::AssocItemContainer::TraitContainer = tcx.associated_item(def_id).container {
|
||||
// for traits, emit `type Effects: TyCompat<<(T1::Effects, ..) as Min>::Output>`
|
||||
let tup = Ty::new(tcx, ty::Tuple(preds.effects_min_tys));
|
||||
// FIXME(effects) span
|
||||
let span = tcx.def_span(def_id);
|
||||
let assoc = tcx.require_lang_item(hir::LangItem::EffectsIntersectionOutput, Some(span));
|
||||
let proj = Ty::new_projection(tcx, assoc, [tup]);
|
||||
let self_proj = Ty::new_projection(
|
||||
tcx,
|
||||
def_id.to_def_id(),
|
||||
ty::GenericArgs::identity_for_item(tcx, def_id),
|
||||
);
|
||||
let trait_ = tcx.require_lang_item(hir::LangItem::EffectsTyCompat, Some(span));
|
||||
let trait_ref = ty::TraitRef::new(tcx, trait_, [self_proj, proj]);
|
||||
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
||||
}
|
||||
return ty::EarlyBinder::bind(tcx.arena.alloc_from_iter(predicates));
|
||||
}
|
||||
|
||||
let bounds = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Type(bounds, _),
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
|||
#[instrument(level = "trace", skip(tcx), ret)]
|
||||
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
||||
use rustc_hir::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
|
||||
|
|
@ -84,6 +85,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
return ty::GenericPredicates {
|
||||
parent: Some(tcx.parent(def_id.to_def_id())),
|
||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||
effects_min_tys: ty::List::empty(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -105,6 +107,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
return ty::GenericPredicates {
|
||||
parent: Some(impl_def_id),
|
||||
predicates: tcx.arena.alloc_from_iter(impl_predicates),
|
||||
effects_min_tys: ty::List::empty(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +127,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
// We use an `IndexSet` to preserve order of insertion.
|
||||
// Preserving the order of insertion is important here so as not to break UI tests.
|
||||
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
|
||||
let mut effects_min_tys = Vec::new();
|
||||
|
||||
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
|
||||
if let Node::Item(item) = node {
|
||||
|
|
@ -150,11 +154,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
// on a trait we must also consider the bounds that follow the trait's name,
|
||||
// like `trait Foo: A + B + C`.
|
||||
if let Some(self_bounds) = is_trait {
|
||||
predicates.extend(
|
||||
icx.lowerer()
|
||||
.lower_mono_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
|
||||
.clauses(),
|
||||
let bounds = icx.lowerer().lower_mono_bounds(
|
||||
tcx.types.self_param,
|
||||
self_bounds,
|
||||
PredicateFilter::All,
|
||||
);
|
||||
predicates.extend(bounds.clauses(tcx));
|
||||
effects_min_tys.extend(bounds.effects_min_tys());
|
||||
}
|
||||
|
||||
// In default impls, we can assume that the self type implements
|
||||
|
|
@ -187,7 +193,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
param.span,
|
||||
);
|
||||
trace!(?bounds);
|
||||
predicates.extend(bounds.clauses());
|
||||
predicates.extend(bounds.clauses(tcx));
|
||||
trace!(?predicates);
|
||||
}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
|
|
@ -238,7 +244,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
bound_vars,
|
||||
OnlySelfBounds(false),
|
||||
);
|
||||
predicates.extend(bounds.clauses());
|
||||
predicates.extend(bounds.clauses(tcx));
|
||||
effects_min_tys.extend(bounds.effects_min_tys());
|
||||
}
|
||||
|
||||
hir::WherePredicate::RegionPredicate(region_pred) => {
|
||||
|
|
@ -297,7 +304,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
// and the duplicated parameter, to ensure that they do not get out of sync.
|
||||
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
|
||||
let opaque_ty_node = tcx.parent_hir_node(hir_id);
|
||||
let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
|
||||
let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node
|
||||
else {
|
||||
bug!("unexpected {opaque_ty_node:?}")
|
||||
};
|
||||
debug!(?lifetimes);
|
||||
|
|
@ -306,9 +314,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
debug!(?predicates);
|
||||
}
|
||||
|
||||
// add `Self::Effects: Compat<HOST>` to ensure non-const impls don't get called
|
||||
// in const contexts.
|
||||
if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node
|
||||
&& let Some(host_effect_index) = generics.host_effect_index
|
||||
{
|
||||
let parent = generics.parent.unwrap();
|
||||
let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else {
|
||||
bug!("associated_type_for_effects returned None when there is host effect in generics");
|
||||
};
|
||||
let effects =
|
||||
Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent));
|
||||
let param = generics.param_at(host_effect_index, tcx);
|
||||
let span = tcx.def_span(param.def_id);
|
||||
let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param));
|
||||
let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span));
|
||||
let trait_ref =
|
||||
ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]);
|
||||
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
||||
}
|
||||
|
||||
ty::GenericPredicates {
|
||||
parent: generics.parent,
|
||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||
effects_min_tys: tcx.mk_type_list(&effects_min_tys),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,6 +488,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
|||
ty::GenericPredicates {
|
||||
parent: predicates_and_bounds.parent,
|
||||
predicates: tcx.arena.alloc_slice(&predicates),
|
||||
effects_min_tys: predicates_and_bounds.effects_min_tys,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -510,6 +540,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
|||
return GenericPredicates {
|
||||
parent: parent_preds.parent,
|
||||
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
|
||||
effects_min_tys: parent_preds.effects_min_tys,
|
||||
};
|
||||
}
|
||||
gather_explicit_predicates_of(tcx, def_id)
|
||||
|
|
@ -519,21 +550,21 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
|||
/// Ensures that the super-predicates of the trait with a `DefId`
|
||||
/// of `trait_def_id` are lowered and stored. This also ensures that
|
||||
/// the transitive super-predicates are lowered.
|
||||
pub(super) fn super_predicates_of(
|
||||
pub(super) fn explicit_super_predicates_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: LocalDefId,
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
|
||||
}
|
||||
|
||||
pub(super) fn super_predicates_that_define_assoc_item(
|
||||
pub(super) fn explicit_supertraits_containing_assoc_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
(trait_def_id, assoc_name): (DefId, Ident),
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
|
||||
}
|
||||
|
||||
pub(super) fn implied_predicates_of(
|
||||
pub(super) fn explicit_implied_predicates_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: LocalDefId,
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
|
|
@ -560,7 +591,7 @@ pub(super) fn implied_predicates_with_filter(
|
|||
// if `assoc_name` is None, then the query should've been redirected to an
|
||||
// external provider
|
||||
assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
|
||||
return tcx.super_predicates_of(trait_def_id);
|
||||
return tcx.explicit_super_predicates_of(trait_def_id);
|
||||
};
|
||||
|
||||
let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
|
||||
|
|
@ -587,7 +618,7 @@ pub(super) fn implied_predicates_with_filter(
|
|||
|
||||
// Combine the two lists to form the complete set of superbounds:
|
||||
let implied_bounds =
|
||||
&*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
|
||||
&*tcx.arena.alloc_from_iter(superbounds.clauses(tcx).chain(where_bounds_that_match));
|
||||
debug!(?implied_bounds);
|
||||
|
||||
// Now require that immediate supertraits are lowered, which will, in
|
||||
|
|
@ -601,7 +632,7 @@ pub(super) fn implied_predicates_with_filter(
|
|||
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
||||
&& bound.polarity == ty::PredicatePolarity::Positive
|
||||
{
|
||||
tcx.at(span).super_predicates_of(bound.def_id());
|
||||
tcx.at(span).explicit_super_predicates_of(bound.def_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -611,14 +642,18 @@ pub(super) fn implied_predicates_with_filter(
|
|||
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
||||
&& bound.polarity == ty::PredicatePolarity::Positive
|
||||
{
|
||||
tcx.at(span).implied_predicates_of(bound.def_id());
|
||||
tcx.at(span).explicit_implied_predicates_of(bound.def_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
ty::GenericPredicates { parent: None, predicates: implied_bounds }
|
||||
ty::GenericPredicates {
|
||||
parent: None,
|
||||
predicates: implied_bounds,
|
||||
effects_min_tys: ty::List::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the predicates defined on `item_def_id` of the form
|
||||
|
|
@ -744,7 +779,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
bounds.clauses().collect()
|
||||
bounds.clauses(self.tcx).collect()
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
|
|
|||
|
|
@ -951,7 +951,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
GenericParamKind::Const { ty, default, is_host_effect: _ } => {
|
||||
GenericParamKind::Const { ty, default, .. } => {
|
||||
self.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
self.visit_body(self.tcx.hir().body(default.body));
|
||||
|
|
@ -1760,7 +1760,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
|
||||
break Some((bound_vars.into_iter().collect(), assoc_item));
|
||||
}
|
||||
let predicates = tcx.super_predicates_that_define_assoc_item((def_id, assoc_name));
|
||||
let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_name));
|
||||
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
||||
let bound_predicate = pred.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
|
|
|
|||
|
|
@ -1699,3 +1699,9 @@ pub struct InvalidReceiverTy<'tcx> {
|
|||
pub span: Span,
|
||||
pub receiver_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_effects_without_next_solver)]
|
||||
#[note]
|
||||
#[help]
|
||||
pub struct EffectsWithoutNextSolver;
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
| GenericParamDefKind::Lifetime,
|
||||
_,
|
||||
) => {
|
||||
// FIXME(effects): this should be removed
|
||||
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
|
||||
// This comes from the following example:
|
||||
//
|
||||
|
|
@ -445,7 +446,7 @@ pub(crate) fn check_generic_arg_count(
|
|||
.own_params
|
||||
.iter()
|
||||
.filter(|param| {
|
||||
matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. })
|
||||
matches!(param.kind, ty::GenericParamDefKind::Const { synthetic: true, .. })
|
||||
})
|
||||
.count();
|
||||
let named_const_param_count = param_counts.consts - synth_const_param_count;
|
||||
|
|
|
|||
|
|
@ -698,7 +698,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
);
|
||||
|
||||
debug!(?poly_trait_ref);
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||
bounds.push_trait_bound(
|
||||
tcx,
|
||||
self.item_def_id().to_def_id(),
|
||||
poly_trait_ref,
|
||||
span,
|
||||
polarity,
|
||||
constness,
|
||||
);
|
||||
|
||||
let mut dup_constraints = FxIndexMap::default();
|
||||
for constraint in trait_segment.args().constraints {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let mut trait_bounds = vec![];
|
||||
let mut projection_bounds = vec![];
|
||||
for (pred, span) in bounds.clauses() {
|
||||
for (pred, span) in bounds.clauses(tcx) {
|
||||
let bound_pred = pred.kind();
|
||||
match bound_pred.skip_binder() {
|
||||
ty::ClauseKind::Trait(trait_pred) => {
|
||||
|
|
@ -133,7 +133,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
tcx.associated_items(pred.def_id())
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.filter(|item| {
|
||||
!item.is_impl_trait_in_trait() && !item.is_effects_desugaring
|
||||
})
|
||||
.map(|item| item.def_id),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,6 +151,12 @@ pub fn provide(providers: &mut Providers) {
|
|||
pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
let _prof_timer = tcx.sess.timer("type_check_crate");
|
||||
|
||||
// FIXME(effects): remove once effects is implemented in old trait solver
|
||||
// or if the next solver is stabilized.
|
||||
if tcx.features().effects && !tcx.next_trait_solver_globally() {
|
||||
tcx.dcx().emit_err(errors::EffectsWithoutNextSolver);
|
||||
}
|
||||
|
||||
tcx.sess.time("coherence_checking", || {
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
let _ = tcx.ensure().check_mod_type_wf(module);
|
||||
|
|
@ -169,6 +175,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
tcx.sess.time("variance_dumping", || variance::dump::variances(tcx));
|
||||
collect::dump::opaque_hidden_types(tcx);
|
||||
collect::dump::predicates_and_item_bounds(tcx);
|
||||
collect::dump::def_parents(tcx);
|
||||
}
|
||||
|
||||
// Make sure we evaluate all static and (non-associated) const items, even if unused.
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ impl<'a> State<'a> {
|
|||
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
|
||||
}
|
||||
hir::ItemKind::Impl(&hir::Impl {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
|
|
@ -599,6 +600,10 @@ impl<'a> State<'a> {
|
|||
self.print_safety(safety);
|
||||
self.word_nbsp("impl");
|
||||
|
||||
if let hir::Constness::Const = constness {
|
||||
self.word_nbsp("const");
|
||||
}
|
||||
|
||||
if !generics.params.is_empty() {
|
||||
self.print_generic_params(generics.params);
|
||||
self.space();
|
||||
|
|
@ -2144,7 +2149,7 @@ impl<'a> State<'a> {
|
|||
self.print_type(default);
|
||||
}
|
||||
}
|
||||
GenericParamKind::Const { ty, ref default, is_host_effect: _ } => {
|
||||
GenericParamKind::Const { ty, ref default, is_host_effect: _, synthetic: _ } => {
|
||||
self.word_space(":");
|
||||
self.print_type(ty);
|
||||
if let Some(default) = default {
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
} else {
|
||||
errors::CannotCastToBoolHelp::Unsupported(self.span)
|
||||
};
|
||||
fcx.tcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
|
||||
fcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help });
|
||||
}
|
||||
CastError::CastToChar => {
|
||||
let mut err = type_error_struct!(
|
||||
|
|
|
|||
|
|
@ -1797,16 +1797,16 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
err.subdiagnostic(SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends });
|
||||
}
|
||||
|
||||
fn report_return_mismatched_types<'a>(
|
||||
fn report_return_mismatched_types<'infcx>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
ty_err: TypeError<'tcx>,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
fcx: &'infcx FnCtxt<'_, 'tcx>,
|
||||
block_or_return_id: hir::HirId,
|
||||
expression: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> Diag<'a> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
|
||||
|
||||
let due_to_block = matches!(fcx.tcx.hir_node(block_or_return_id), hir::Node::Block(..));
|
||||
|
|
|
|||
|
|
@ -172,21 +172,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn demand_suptype_diag(
|
||||
&self,
|
||||
&'a self,
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'a>> {
|
||||
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn demand_suptype_with_origin(
|
||||
&self,
|
||||
&'a self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'a>> {
|
||||
self.at(cause, self.param_env)
|
||||
.sup(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
|
|
@ -200,20 +200,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn demand_eqtype_diag(
|
||||
&self,
|
||||
&'a self,
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'a>> {
|
||||
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
pub fn demand_eqtype_with_origin(
|
||||
&self,
|
||||
&'a self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'a>> {
|
||||
self.at(cause, self.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
|
|
@ -247,13 +247,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// will be permitted if the diverges flag is currently "always".
|
||||
#[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
|
||||
pub fn demand_coerce_diag(
|
||||
&self,
|
||||
&'a self,
|
||||
mut expr: &'tcx hir::Expr<'tcx>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> Result<Ty<'tcx>, Diag<'tcx>> {
|
||||
) -> Result<Ty<'tcx>, Diag<'a>> {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
|
||||
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Set expectation to error in that case and set tainted
|
||||
// by error (#114529)
|
||||
let coerce_to = opt_coerce_to.unwrap_or_else(|| {
|
||||
let guar = tcx.dcx().span_delayed_bug(
|
||||
let guar = self.dcx().span_delayed_bug(
|
||||
expr.span,
|
||||
"illegal break with value found but no error reported",
|
||||
);
|
||||
|
|
@ -1716,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
error_happened = true;
|
||||
let guar = if let Some(prev_span) = seen_fields.get(&ident) {
|
||||
tcx.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
|
||||
self.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
|
||||
span: field.ident.span,
|
||||
prev_span: *prev_span,
|
||||
ident,
|
||||
|
|
@ -1757,7 +1757,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if adt_kind == AdtKind::Union {
|
||||
if hir_fields.len() != 1 {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
self.dcx(),
|
||||
span,
|
||||
E0784,
|
||||
"union expressions should have exactly one field",
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue