Auto merge of #106656 - JohnTitor:rollup-rk2qltg, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #105034 (Add example for iterator_flatten) - #105708 (Enable atomic cas for bpf targets) - #106175 (Fix bad import suggestion with nested `use` tree) - #106204 (No need to take opaques in `check_type_bounds`) - #106387 (Revert "bootstrap: Get rid of `tail_args` in `stream_cargo`") - #106636 (Accept old spelling of Fuchsia target triples) - #106639 (update Miri) - #106640 (update test for inductive canonical cycles) - #106647 (rustdoc: merge common CSS for `a`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
deba5ddd07
48 changed files with 553 additions and 177 deletions
|
@ -318,7 +318,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||||
|
|
||||||
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
||||||
// tests to pass
|
// tests to pass
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let _ = infcx.take_opaque_types();
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
definition_ty
|
definition_ty
|
||||||
|
|
|
@ -209,7 +209,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
translate_outlives_facts(&mut checker);
|
translate_outlives_facts(&mut checker);
|
||||||
let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let opaque_type_values = infcx.take_opaque_types();
|
||||||
|
|
||||||
let opaque_type_values = opaque_type_values
|
let opaque_type_values = opaque_type_values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
@ -58,6 +58,6 @@ pub fn is_subtype<'tcx>(
|
||||||
// even if they're constrained in our current function.
|
// even if they're constrained in our current function.
|
||||||
//
|
//
|
||||||
// It seems very unlikely that this hides any bugs.
|
// It seems very unlikely that this hides any bugs.
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let _ = infcx.take_opaque_types();
|
||||||
errors.is_empty()
|
errors.is_empty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,7 +475,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean up after ourselves
|
// Clean up after ourselves
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let _ = infcx.take_opaque_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_enum_of_nonnullable_ptr<'tcx>(
|
fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||||
|
|
|
@ -424,7 +424,7 @@ fn compare_asyncness<'tcx>(
|
||||||
ty::Alias(ty::Opaque, ..) => {
|
ty::Alias(ty::Opaque, ..) => {
|
||||||
// allow both `async fn foo()` and `fn foo() -> impl Future`
|
// allow both `async fn foo()` and `fn foo() -> impl Future`
|
||||||
}
|
}
|
||||||
ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
|
ty::Error(_) => {
|
||||||
// We don't know if it's ok, but at least it's already an error.
|
// We don't know if it's ok, but at least it's already an error.
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1972,22 +1972,6 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||||
&outlives_environment,
|
&outlives_environment,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
|
||||||
for (key, value) in constraints {
|
|
||||||
infcx
|
|
||||||
.err_ctxt()
|
|
||||||
.report_mismatched_types(
|
|
||||||
&ObligationCause::misc(
|
|
||||||
value.hidden_type.span,
|
|
||||||
tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()),
|
|
||||||
),
|
|
||||||
tcx.mk_opaque(key.def_id.to_def_id(), key.substs),
|
|
||||||
value.hidden_type.ty,
|
|
||||||
TypeError::Mismatch,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -534,8 +534,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn visit_opaque_types(&mut self) {
|
fn visit_opaque_types(&mut self) {
|
||||||
let opaque_types =
|
let opaque_types = self.fcx.infcx.take_opaque_types();
|
||||||
self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
|
||||||
for (opaque_type_key, decl) in opaque_types {
|
for (opaque_type_key, decl) in opaque_types {
|
||||||
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
|
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
|
||||||
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
|
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
|
||||||
|
|
|
@ -156,10 +156,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
/// As the new solver does canonicalization slightly differently, this is also used there
|
/// As the new solver does canonicalization slightly differently, this is also used there
|
||||||
/// for now. This should hopefully change fairly soon.
|
/// for now. This should hopefully change fairly soon.
|
||||||
pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
|
pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
|
||||||
self.inner
|
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
|
||||||
.borrow_mut()
|
|
||||||
.opaque_type_storage
|
|
||||||
.take_opaque_types()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
|
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -1338,6 +1338,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
var_infos
|
var_infos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
|
pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
|
||||||
|
debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error);
|
||||||
|
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
|
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
|
||||||
self.resolve_vars_if_possible(t).to_string()
|
self.resolve_vars_if_possible(t).to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,6 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", ret)]
|
|
||||||
pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> {
|
|
||||||
std::mem::take(&mut self.opaque_types)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn with_log<'a>(
|
pub(crate) fn with_log<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
|
|
|
@ -161,6 +161,7 @@ impl<'a> Resolver<'a> {
|
||||||
found_use,
|
found_use,
|
||||||
DiagnosticMode::Normal,
|
DiagnosticMode::Normal,
|
||||||
path,
|
path,
|
||||||
|
"",
|
||||||
);
|
);
|
||||||
err.emit();
|
err.emit();
|
||||||
} else if let Some((span, msg, sugg, appl)) = suggestion {
|
} else if let Some((span, msg, sugg, appl)) = suggestion {
|
||||||
|
@ -690,6 +691,7 @@ impl<'a> Resolver<'a> {
|
||||||
FoundUse::Yes,
|
FoundUse::Yes,
|
||||||
DiagnosticMode::Pattern,
|
DiagnosticMode::Pattern,
|
||||||
vec![],
|
vec![],
|
||||||
|
"",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err
|
err
|
||||||
|
@ -1344,6 +1346,7 @@ impl<'a> Resolver<'a> {
|
||||||
FoundUse::Yes,
|
FoundUse::Yes,
|
||||||
DiagnosticMode::Normal,
|
DiagnosticMode::Normal,
|
||||||
vec![],
|
vec![],
|
||||||
|
"",
|
||||||
);
|
);
|
||||||
|
|
||||||
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
|
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
|
||||||
|
@ -2309,7 +2312,7 @@ enum FoundUse {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
|
/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
|
||||||
enum DiagnosticMode {
|
pub(crate) enum DiagnosticMode {
|
||||||
Normal,
|
Normal,
|
||||||
/// The binding is part of a pattern
|
/// The binding is part of a pattern
|
||||||
Pattern,
|
Pattern,
|
||||||
|
@ -2324,6 +2327,8 @@ pub(crate) fn import_candidates(
|
||||||
// This is `None` if all placement locations are inside expansions
|
// This is `None` if all placement locations are inside expansions
|
||||||
use_placement_span: Option<Span>,
|
use_placement_span: Option<Span>,
|
||||||
candidates: &[ImportSuggestion],
|
candidates: &[ImportSuggestion],
|
||||||
|
mode: DiagnosticMode,
|
||||||
|
append: &str,
|
||||||
) {
|
) {
|
||||||
show_candidates(
|
show_candidates(
|
||||||
session,
|
session,
|
||||||
|
@ -2333,8 +2338,9 @@ pub(crate) fn import_candidates(
|
||||||
candidates,
|
candidates,
|
||||||
Instead::Yes,
|
Instead::Yes,
|
||||||
FoundUse::Yes,
|
FoundUse::Yes,
|
||||||
DiagnosticMode::Import,
|
mode,
|
||||||
vec![],
|
vec![],
|
||||||
|
append,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2352,6 +2358,7 @@ fn show_candidates(
|
||||||
found_use: FoundUse,
|
found_use: FoundUse,
|
||||||
mode: DiagnosticMode,
|
mode: DiagnosticMode,
|
||||||
path: Vec<Segment>,
|
path: Vec<Segment>,
|
||||||
|
append: &str,
|
||||||
) {
|
) {
|
||||||
if candidates.is_empty() {
|
if candidates.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -2416,7 +2423,7 @@ fn show_candidates(
|
||||||
// produce an additional newline to separate the new use statement
|
// produce an additional newline to separate the new use statement
|
||||||
// from the directly following item.
|
// from the directly following item.
|
||||||
let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" };
|
let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" };
|
||||||
candidate.0 = format!("{}{};\n{}", add_use, &candidate.0, additional_newline);
|
candidate.0 = format!("{add_use}{}{append};\n{additional_newline}", &candidate.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
err.span_suggestions(
|
err.span_suggestions(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! A bunch of methods and structures more or less related to resolving imports.
|
//! A bunch of methods and structures more or less related to resolving imports.
|
||||||
|
|
||||||
use crate::diagnostics::{import_candidates, Suggestion};
|
use crate::diagnostics::{import_candidates, DiagnosticMode, Suggestion};
|
||||||
use crate::Determinacy::{self, *};
|
use crate::Determinacy::{self, *};
|
||||||
use crate::Namespace::*;
|
use crate::Namespace::*;
|
||||||
use crate::{module_to_string, names_to_string, ImportSuggestion};
|
use crate::{module_to_string, names_to_string, ImportSuggestion};
|
||||||
|
@ -402,7 +402,7 @@ struct UnresolvedImportError {
|
||||||
label: Option<String>,
|
label: Option<String>,
|
||||||
note: Option<String>,
|
note: Option<String>,
|
||||||
suggestion: Option<Suggestion>,
|
suggestion: Option<Suggestion>,
|
||||||
candidate: Option<Vec<ImportSuggestion>>,
|
candidates: Option<Vec<ImportSuggestion>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImportResolver<'a, 'b> {
|
pub struct ImportResolver<'a, 'b> {
|
||||||
|
@ -475,12 +475,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
errors = vec![];
|
errors = vec![];
|
||||||
}
|
}
|
||||||
if seen_spans.insert(err.span) {
|
if seen_spans.insert(err.span) {
|
||||||
let path = import_path_to_string(
|
errors.push((import, err));
|
||||||
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
|
||||||
&import.kind,
|
|
||||||
err.span,
|
|
||||||
);
|
|
||||||
errors.push((path, err));
|
|
||||||
prev_root_id = import.root_id;
|
prev_root_id = import.root_id;
|
||||||
}
|
}
|
||||||
} else if is_indeterminate {
|
} else if is_indeterminate {
|
||||||
|
@ -494,10 +489,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
label: None,
|
label: None,
|
||||||
note: None,
|
note: None,
|
||||||
suggestion: None,
|
suggestion: None,
|
||||||
candidate: None,
|
candidates: None,
|
||||||
};
|
};
|
||||||
|
// FIXME: there should be a better way of doing this than
|
||||||
|
// formatting this as a string then checking for `::`
|
||||||
if path.contains("::") {
|
if path.contains("::") {
|
||||||
errors.push((path, err))
|
errors.push((import, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,7 +504,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn throw_unresolved_import_error(&self, errors: Vec<(String, UnresolvedImportError)>) {
|
fn throw_unresolved_import_error(&self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) {
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -516,7 +513,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
const MAX_LABEL_COUNT: usize = 10;
|
const MAX_LABEL_COUNT: usize = 10;
|
||||||
|
|
||||||
let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
|
let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
|
||||||
let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::<Vec<_>>();
|
let paths = errors
|
||||||
|
.iter()
|
||||||
|
.map(|(import, err)| {
|
||||||
|
let path = import_path_to_string(
|
||||||
|
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
||||||
|
&import.kind,
|
||||||
|
err.span,
|
||||||
|
);
|
||||||
|
format!("`{path}`")
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
|
let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
|
||||||
|
|
||||||
let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg);
|
let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg);
|
||||||
|
@ -525,7 +532,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
diag.note(note);
|
diag.note(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
|
for (import, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
|
||||||
if let Some(label) = err.label {
|
if let Some(label) = err.label {
|
||||||
diag.span_label(err.span, label);
|
diag.span_label(err.span, label);
|
||||||
}
|
}
|
||||||
|
@ -538,14 +545,36 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
diag.multipart_suggestion(&msg, suggestions, applicability);
|
diag.multipart_suggestion(&msg, suggestions, applicability);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(candidate) = &err.candidate {
|
if let Some(candidates) = &err.candidates {
|
||||||
import_candidates(
|
match &import.kind {
|
||||||
|
ImportKind::Single { nested: false, source, target, .. } => import_candidates(
|
||||||
self.r.session,
|
self.r.session,
|
||||||
&self.r.untracked.source_span,
|
&self.r.untracked.source_span,
|
||||||
&mut diag,
|
&mut diag,
|
||||||
Some(err.span),
|
Some(err.span),
|
||||||
&candidate,
|
&candidates,
|
||||||
)
|
DiagnosticMode::Import,
|
||||||
|
(source != target)
|
||||||
|
.then(|| format!(" as {target}"))
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or(""),
|
||||||
|
),
|
||||||
|
ImportKind::Single { nested: true, source, target, .. } => {
|
||||||
|
import_candidates(
|
||||||
|
self.r.session,
|
||||||
|
&self.r.untracked.source_span,
|
||||||
|
&mut diag,
|
||||||
|
None,
|
||||||
|
&candidates,
|
||||||
|
DiagnosticMode::Normal,
|
||||||
|
(source != target)
|
||||||
|
.then(|| format!(" as {target}"))
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or(""),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,14 +736,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
String::from("a similar path exists"),
|
String::from("a similar path exists"),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)),
|
)),
|
||||||
candidate: None,
|
candidates: None,
|
||||||
},
|
},
|
||||||
None => UnresolvedImportError {
|
None => UnresolvedImportError {
|
||||||
span,
|
span,
|
||||||
label: Some(label),
|
label: Some(label),
|
||||||
note: None,
|
note: None,
|
||||||
suggestion,
|
suggestion,
|
||||||
candidate: None,
|
candidates: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return Some(err);
|
return Some(err);
|
||||||
|
@ -761,7 +790,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
)),
|
)),
|
||||||
note: None,
|
note: None,
|
||||||
suggestion: None,
|
suggestion: None,
|
||||||
candidate: None,
|
candidates: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,7 +902,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
|
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
|
||||||
let names = resolutions
|
let names = resolutions
|
||||||
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
|
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
|
||||||
if *i == ident {
|
if i.name == ident.name {
|
||||||
return None;
|
return None;
|
||||||
} // Never suggest the same name
|
} // Never suggest the same name
|
||||||
match *resolution.borrow() {
|
match *resolution.borrow() {
|
||||||
|
@ -943,7 +972,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||||
label: Some(label),
|
label: Some(label),
|
||||||
note,
|
note,
|
||||||
suggestion,
|
suggestion,
|
||||||
candidate: if !parent_suggestion.is_empty() {
|
candidates: if !parent_suggestion.is_empty() {
|
||||||
Some(parent_suggestion)
|
Some(parent_suggestion)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
1
compiler/rustc_target/src/spec/aarch64_fuchsia.rs
Normal file
1
compiler/rustc_target/src/spec/aarch64_fuchsia.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub use crate::spec::aarch64_unknown_fuchsia::target;
|
|
@ -6,7 +6,7 @@ pub fn opts(endian: Endian) -> TargetOptions {
|
||||||
allow_asm: true,
|
allow_asm: true,
|
||||||
endian,
|
endian,
|
||||||
linker_flavor: LinkerFlavor::Bpf,
|
linker_flavor: LinkerFlavor::Bpf,
|
||||||
atomic_cas: false,
|
atomic_cas: true,
|
||||||
dynamic_linking: true,
|
dynamic_linking: true,
|
||||||
no_builtins: true,
|
no_builtins: true,
|
||||||
panic_strategy: PanicStrategy::Abort,
|
panic_strategy: PanicStrategy::Abort,
|
||||||
|
@ -19,6 +19,10 @@ pub fn opts(endian: Endian) -> TargetOptions {
|
||||||
obj_is_bitcode: true,
|
obj_is_bitcode: true,
|
||||||
requires_lto: false,
|
requires_lto: false,
|
||||||
singlethread: true,
|
singlethread: true,
|
||||||
|
// When targeting the `v3` cpu in llvm, 32-bit atomics are also supported.
|
||||||
|
// But making this value change based on the target cpu can be mostly confusing
|
||||||
|
// and would require a bit of a refactor.
|
||||||
|
min_atomic_width: Some(64),
|
||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1109,7 +1109,11 @@ supported_targets! {
|
||||||
("x86_64-apple-darwin", x86_64_apple_darwin),
|
("x86_64-apple-darwin", x86_64_apple_darwin),
|
||||||
("i686-apple-darwin", i686_apple_darwin),
|
("i686-apple-darwin", i686_apple_darwin),
|
||||||
|
|
||||||
|
// FIXME(#106649): Remove aarch64-fuchsia in favor of aarch64-unknown-fuchsia
|
||||||
|
("aarch64-fuchsia", aarch64_fuchsia),
|
||||||
("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
|
("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
|
||||||
|
// FIXME(#106649): Remove x86_64-fuchsia in favor of x86_64-unknown-fuchsia
|
||||||
|
("x86_64-fuchsia", x86_64_fuchsia),
|
||||||
("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
|
("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
|
||||||
|
|
||||||
("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
|
("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
|
||||||
|
|
1
compiler/rustc_target/src/spec/x86_64_fuchsia.rs
Normal file
1
compiler/rustc_target/src/spec/x86_64_fuchsia.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub use crate::spec::x86_64_unknown_fuchsia::target;
|
|
@ -450,9 +450,6 @@ pub fn impossible_predicates<'tcx>(
|
||||||
}
|
}
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
|
|
||||||
// Clean up after ourselves
|
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
|
||||||
|
|
||||||
let result = !errors.is_empty();
|
let result = !errors.is_empty();
|
||||||
debug!("impossible_predicates = {:?}", result);
|
debug!("impossible_predicates = {:?}", result);
|
||||||
result
|
result
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub fn codegen_select_candidate<'tcx>(
|
||||||
// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
|
// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
|
||||||
// as they will get constrained elsewhere, too.
|
// as they will get constrained elsewhere, too.
|
||||||
// (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
|
// (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
|
||||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
let _ = infcx.take_opaque_types();
|
||||||
|
|
||||||
Ok(&*tcx.arena.alloc(impl_source))
|
Ok(&*tcx.arena.alloc(impl_source))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1514,6 +1514,18 @@ pub trait Iterator {
|
||||||
/// assert_eq!(merged, "alphabetagamma");
|
/// assert_eq!(merged, "alphabetagamma");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// Flattening works on any `IntoIterator` type, including `Option` and `Result`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let options = vec![Some(123), Some(321), None, Some(231)];
|
||||||
|
/// let flattened_options: Vec<_> = options.into_iter().flatten().collect();
|
||||||
|
/// assert_eq!(flattened_options, vec![123, 321, 231]);
|
||||||
|
///
|
||||||
|
/// let results = vec![Ok(123), Ok(321), Err(456), Ok(231)];
|
||||||
|
/// let flattened_results: Vec<_> = results.into_iter().flatten().collect();
|
||||||
|
/// assert_eq!(flattened_results, vec![123, 321, 231]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// Flattening only removes one level of nesting at a time:
|
/// Flattening only removes one level of nesting at a time:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -99,13 +99,20 @@ impl Step for Std {
|
||||||
cargo_subcommand(builder.kind),
|
cargo_subcommand(builder.kind),
|
||||||
);
|
);
|
||||||
std_cargo(builder, target, compiler.stage, &mut cargo);
|
std_cargo(builder, target, compiler.stage, &mut cargo);
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
builder.info(&format!(
|
builder.info(&format!(
|
||||||
"Checking stage{} library artifacts ({} -> {})",
|
"Checking stage{} library artifacts ({} -> {})",
|
||||||
builder.top_stage, &compiler.host, target
|
builder.top_stage, &compiler.host, target
|
||||||
));
|
));
|
||||||
run_cargo(builder, cargo, &libstd_stamp(builder, compiler, target), vec![], true, false);
|
run_cargo(
|
||||||
|
builder,
|
||||||
|
cargo,
|
||||||
|
args(builder),
|
||||||
|
&libstd_stamp(builder, compiler, target),
|
||||||
|
vec![],
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
// We skip populating the sysroot in non-zero stage because that'll lead
|
// We skip populating the sysroot in non-zero stage because that'll lead
|
||||||
// to rlib/rmeta conflicts if std gets built during this session.
|
// to rlib/rmeta conflicts if std gets built during this session.
|
||||||
|
@ -149,7 +156,6 @@ impl Step for Std {
|
||||||
for krate in builder.in_tree_crates("test", Some(target)) {
|
for krate in builder.in_tree_crates("test", Some(target)) {
|
||||||
cargo.arg("-p").arg(krate.name);
|
cargo.arg("-p").arg(krate.name);
|
||||||
}
|
}
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
builder.info(&format!(
|
builder.info(&format!(
|
||||||
"Checking stage{} library test/bench/example targets ({} -> {})",
|
"Checking stage{} library test/bench/example targets ({} -> {})",
|
||||||
|
@ -158,6 +164,7 @@ impl Step for Std {
|
||||||
run_cargo(
|
run_cargo(
|
||||||
builder,
|
builder,
|
||||||
cargo,
|
cargo,
|
||||||
|
args(builder),
|
||||||
&libstd_test_stamp(builder, compiler, target),
|
&libstd_test_stamp(builder, compiler, target),
|
||||||
vec![],
|
vec![],
|
||||||
true,
|
true,
|
||||||
|
@ -226,13 +233,20 @@ impl Step for Rustc {
|
||||||
for krate in builder.in_tree_crates("rustc-main", Some(target)) {
|
for krate in builder.in_tree_crates("rustc-main", Some(target)) {
|
||||||
cargo.arg("-p").arg(krate.name);
|
cargo.arg("-p").arg(krate.name);
|
||||||
}
|
}
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
builder.info(&format!(
|
builder.info(&format!(
|
||||||
"Checking stage{} compiler artifacts ({} -> {})",
|
"Checking stage{} compiler artifacts ({} -> {})",
|
||||||
builder.top_stage, &compiler.host, target
|
builder.top_stage, &compiler.host, target
|
||||||
));
|
));
|
||||||
run_cargo(builder, cargo, &librustc_stamp(builder, compiler, target), vec![], true, false);
|
run_cargo(
|
||||||
|
builder,
|
||||||
|
cargo,
|
||||||
|
args(builder),
|
||||||
|
&librustc_stamp(builder, compiler, target),
|
||||||
|
vec![],
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
let libdir = builder.sysroot_libdir(compiler, target);
|
let libdir = builder.sysroot_libdir(compiler, target);
|
||||||
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
|
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
|
||||||
|
@ -279,7 +293,6 @@ impl Step for CodegenBackend {
|
||||||
.arg("--manifest-path")
|
.arg("--manifest-path")
|
||||||
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
|
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
|
||||||
rustc_cargo_env(builder, &mut cargo, target);
|
rustc_cargo_env(builder, &mut cargo, target);
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
builder.info(&format!(
|
builder.info(&format!(
|
||||||
"Checking stage{} {} artifacts ({} -> {})",
|
"Checking stage{} {} artifacts ({} -> {})",
|
||||||
|
@ -289,6 +302,7 @@ impl Step for CodegenBackend {
|
||||||
run_cargo(
|
run_cargo(
|
||||||
builder,
|
builder,
|
||||||
cargo,
|
cargo,
|
||||||
|
args(builder),
|
||||||
&codegen_backend_stamp(builder, compiler, target, backend),
|
&codegen_backend_stamp(builder, compiler, target, backend),
|
||||||
vec![],
|
vec![],
|
||||||
true,
|
true,
|
||||||
|
@ -345,13 +359,19 @@ impl Step for RustAnalyzer {
|
||||||
cargo.arg("--benches");
|
cargo.arg("--benches");
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
builder.info(&format!(
|
builder.info(&format!(
|
||||||
"Checking stage{} {} artifacts ({} -> {})",
|
"Checking stage{} {} artifacts ({} -> {})",
|
||||||
compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
|
compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
|
||||||
));
|
));
|
||||||
run_cargo(builder, cargo, &stamp(builder, compiler, target), vec![], true, false);
|
run_cargo(
|
||||||
|
builder,
|
||||||
|
cargo,
|
||||||
|
args(builder),
|
||||||
|
&stamp(builder, compiler, target),
|
||||||
|
vec![],
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
/// Cargo's output path in a given stage, compiled by a particular
|
/// Cargo's output path in a given stage, compiled by a particular
|
||||||
/// compiler for the specified target.
|
/// compiler for the specified target.
|
||||||
|
@ -405,8 +425,6 @@ macro_rules! tool_check_step {
|
||||||
cargo.arg("--all-targets");
|
cargo.arg("--all-targets");
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo.args(args(builder));
|
|
||||||
|
|
||||||
// Enable internal lints for clippy and rustdoc
|
// Enable internal lints for clippy and rustdoc
|
||||||
// NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
|
// NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
|
||||||
// See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
|
// See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
|
||||||
|
@ -422,6 +440,7 @@ macro_rules! tool_check_step {
|
||||||
run_cargo(
|
run_cargo(
|
||||||
builder,
|
builder,
|
||||||
cargo,
|
cargo,
|
||||||
|
args(builder),
|
||||||
&stamp(builder, compiler, target),
|
&stamp(builder, compiler, target),
|
||||||
vec![],
|
vec![],
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -144,6 +144,7 @@ impl Step for Std {
|
||||||
run_cargo(
|
run_cargo(
|
||||||
builder,
|
builder,
|
||||||
cargo,
|
cargo,
|
||||||
|
vec![],
|
||||||
&libstd_stamp(builder, compiler, target),
|
&libstd_stamp(builder, compiler, target),
|
||||||
target_deps,
|
target_deps,
|
||||||
false,
|
false,
|
||||||
|
@ -738,6 +739,7 @@ impl Step for Rustc {
|
||||||
run_cargo(
|
run_cargo(
|
||||||
builder,
|
builder,
|
||||||
cargo,
|
cargo,
|
||||||
|
vec![],
|
||||||
&librustc_stamp(builder, compiler, target),
|
&librustc_stamp(builder, compiler, target),
|
||||||
vec![],
|
vec![],
|
||||||
false,
|
false,
|
||||||
|
@ -998,7 +1000,7 @@ impl Step for CodegenBackend {
|
||||||
"Building stage{} codegen backend {} ({} -> {})",
|
"Building stage{} codegen backend {} ({} -> {})",
|
||||||
compiler.stage, backend, &compiler.host, target
|
compiler.stage, backend, &compiler.host, target
|
||||||
));
|
));
|
||||||
let files = run_cargo(builder, cargo, &tmp_stamp, vec![], false, false);
|
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
|
||||||
if builder.config.dry_run() {
|
if builder.config.dry_run() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1424,7 @@ pub fn add_to_sysroot(
|
||||||
pub fn run_cargo(
|
pub fn run_cargo(
|
||||||
builder: &Builder<'_>,
|
builder: &Builder<'_>,
|
||||||
cargo: Cargo,
|
cargo: Cargo,
|
||||||
|
tail_args: Vec<String>,
|
||||||
stamp: &Path,
|
stamp: &Path,
|
||||||
additional_target_deps: Vec<(PathBuf, DependencyType)>,
|
additional_target_deps: Vec<(PathBuf, DependencyType)>,
|
||||||
is_check: bool,
|
is_check: bool,
|
||||||
|
@ -1448,7 +1451,7 @@ pub fn run_cargo(
|
||||||
// files we need to probe for later.
|
// files we need to probe for later.
|
||||||
let mut deps = Vec::new();
|
let mut deps = Vec::new();
|
||||||
let mut toplevel = Vec::new();
|
let mut toplevel = Vec::new();
|
||||||
let ok = stream_cargo(builder, cargo, &mut |msg| {
|
let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
|
||||||
let (filenames, crate_types) = match msg {
|
let (filenames, crate_types) = match msg {
|
||||||
CargoMessage::CompilerArtifact {
|
CargoMessage::CompilerArtifact {
|
||||||
filenames,
|
filenames,
|
||||||
|
@ -1585,6 +1588,7 @@ pub fn run_cargo(
|
||||||
pub fn stream_cargo(
|
pub fn stream_cargo(
|
||||||
builder: &Builder<'_>,
|
builder: &Builder<'_>,
|
||||||
cargo: Cargo,
|
cargo: Cargo,
|
||||||
|
tail_args: Vec<String>,
|
||||||
cb: &mut dyn FnMut(CargoMessage<'_>),
|
cb: &mut dyn FnMut(CargoMessage<'_>),
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut cargo = Command::from(cargo);
|
let mut cargo = Command::from(cargo);
|
||||||
|
@ -1604,6 +1608,10 @@ pub fn stream_cargo(
|
||||||
}
|
}
|
||||||
cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
|
cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
|
||||||
|
|
||||||
|
for arg in tail_args {
|
||||||
|
cargo.arg(arg);
|
||||||
|
}
|
||||||
|
|
||||||
builder.verbose(&format!("running: {:?}", cargo));
|
builder.verbose(&format!("running: {:?}", cargo));
|
||||||
let mut child = match cargo.spawn() {
|
let mut child = match cargo.spawn() {
|
||||||
Ok(child) => child,
|
Ok(child) => child,
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl Step for ToolBuild {
|
||||||
|
|
||||||
builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
|
builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
|
||||||
let mut duplicates = Vec::new();
|
let mut duplicates = Vec::new();
|
||||||
let is_expected = compile::stream_cargo(builder, cargo, &mut |msg| {
|
let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| {
|
||||||
// Only care about big things like the RLS/Cargo for now
|
// Only care about big things like the RLS/Cargo for now
|
||||||
match tool {
|
match tool {
|
||||||
"rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {}
|
"rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {}
|
||||||
|
|
|
@ -124,6 +124,7 @@ target | std | notes
|
||||||
-------|:---:|-------
|
-------|:---:|-------
|
||||||
`aarch64-apple-ios` | ✓ | ARM64 iOS
|
`aarch64-apple-ios` | ✓ | ARM64 iOS
|
||||||
[`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64
|
[`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64
|
||||||
|
`aarch64-fuchsia` | ✓ | Alias for `aarch64-unknown-fuchsia`
|
||||||
`aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia
|
`aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia
|
||||||
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
|
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
|
||||||
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
|
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
|
||||||
|
@ -177,6 +178,7 @@ target | std | notes
|
||||||
`wasm32-wasi` | ✓ | WebAssembly with WASI
|
`wasm32-wasi` | ✓ | WebAssembly with WASI
|
||||||
`x86_64-apple-ios` | ✓ | 64-bit x86 iOS
|
`x86_64-apple-ios` | ✓ | 64-bit x86 iOS
|
||||||
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
|
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
|
||||||
|
`x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia`
|
||||||
`x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia
|
`x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia
|
||||||
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
|
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
|
||||||
`x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos
|
`x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos
|
||||||
|
|
|
@ -253,6 +253,7 @@ h1 a,
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--link-color);
|
color: var(--link-color);
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
ol, ul {
|
ol, ul {
|
||||||
|
@ -662,10 +663,6 @@ nav.sub {
|
||||||
margin: 0 0 15px 0;
|
margin: 0 0 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-section-header {
|
.small-section-header {
|
||||||
/* fields use <span> tags, but should get their own lines */
|
/* fields use <span> tags, but should get their own lines */
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -2,10 +2,7 @@ error[E0432]: unresolved import `my_core`
|
||||||
--> $DIR/extern-prelude-from-opaque-fail.rs:20:9
|
--> $DIR/extern-prelude-from-opaque-fail.rs:20:9
|
||||||
|
|
|
|
||||||
LL | use my_core;
|
LL | use my_core;
|
||||||
| ^^^^^^^
|
| ^^^^^^^ no `my_core` in the root
|
||||||
| |
|
|
||||||
| no `my_core` in the root
|
|
||||||
| help: a similar name exists in the module: `my_core`
|
|
||||||
|
|
||||||
error[E0432]: unresolved import `my_core`
|
error[E0432]: unresolved import `my_core`
|
||||||
--> $DIR/extern-prelude-from-opaque-fail.rs:7:13
|
--> $DIR/extern-prelude-from-opaque-fail.rs:7:13
|
||||||
|
|
27
src/test/ui/imports/bad-import-in-nested.rs
Normal file
27
src/test/ui/imports/bad-import-in-nested.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// edition: 2021
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
mod A {
|
||||||
|
pub(crate) type AA = ();
|
||||||
|
pub(crate) type BB = ();
|
||||||
|
|
||||||
|
mod A2 {
|
||||||
|
use super::{super::C::D::AA, AA as _};
|
||||||
|
//~^ ERROR unresolved import
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod C {
|
||||||
|
pub mod D {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod B {
|
||||||
|
use crate::C::{self, AA};
|
||||||
|
//~^ ERROR unresolved import
|
||||||
|
|
||||||
|
use crate::{A, C::BB};
|
||||||
|
//~^ ERROR unresolved import
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
30
src/test/ui/imports/bad-import-in-nested.stderr
Normal file
30
src/test/ui/imports/bad-import-in-nested.stderr
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
error[E0432]: unresolved import `super::super::C::D::AA`
|
||||||
|
--> $DIR/bad-import-in-nested.rs:10:21
|
||||||
|
|
|
||||||
|
LL | use super::{super::C::D::AA, AA as _};
|
||||||
|
| ^^^^^^^^^^^^^^^ no `AA` in `C::D`
|
||||||
|
|
|
||||||
|
= note: consider importing this type alias instead:
|
||||||
|
crate::A::AA
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `crate::C::AA`
|
||||||
|
--> $DIR/bad-import-in-nested.rs:20:26
|
||||||
|
|
|
||||||
|
LL | use crate::C::{self, AA};
|
||||||
|
| ^^ no `AA` in `C`
|
||||||
|
|
|
||||||
|
= note: consider importing this type alias instead:
|
||||||
|
crate::A::AA
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `crate::C::BB`
|
||||||
|
--> $DIR/bad-import-in-nested.rs:23:20
|
||||||
|
|
|
||||||
|
LL | use crate::{A, C::BB};
|
||||||
|
| ^^^^^ no `BB` in `C`
|
||||||
|
|
|
||||||
|
= note: consider importing this type alias instead:
|
||||||
|
crate::A::BB
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0432`.
|
16
src/test/ui/imports/bad-import-with-rename.rs
Normal file
16
src/test/ui/imports/bad-import-with-rename.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
mod A {
|
||||||
|
pub type B = ();
|
||||||
|
pub type B2 = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
mod C {
|
||||||
|
use crate::D::B as _;
|
||||||
|
//~^ ERROR unresolved import `crate::D::B`
|
||||||
|
|
||||||
|
use crate::D::B2;
|
||||||
|
//~^ ERROR unresolved import `crate::D::B2`
|
||||||
|
}
|
||||||
|
|
||||||
|
mod D {}
|
||||||
|
|
||||||
|
fn main() {}
|
25
src/test/ui/imports/bad-import-with-rename.stderr
Normal file
25
src/test/ui/imports/bad-import-with-rename.stderr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
error[E0432]: unresolved import `crate::D::B`
|
||||||
|
--> $DIR/bad-import-with-rename.rs:7:9
|
||||||
|
|
|
||||||
|
LL | use crate::D::B as _;
|
||||||
|
| ^^^^^^^^^^^^^^^^ no `B` in `D`
|
||||||
|
|
|
||||||
|
help: consider importing this type alias instead
|
||||||
|
|
|
||||||
|
LL | use A::B as _;
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `crate::D::B2`
|
||||||
|
--> $DIR/bad-import-with-rename.rs:10:9
|
||||||
|
|
|
||||||
|
LL | use crate::D::B2;
|
||||||
|
| ^^^^^^^^^^^^ no `B2` in `D`
|
||||||
|
|
|
||||||
|
help: consider importing this type alias instead
|
||||||
|
|
|
||||||
|
LL | use A::B2;
|
||||||
|
| ~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0432`.
|
|
@ -2,10 +2,7 @@ error[E0432]: unresolved import `main`
|
||||||
--> $DIR/inaccessible-test-modules.rs:5:5
|
--> $DIR/inaccessible-test-modules.rs:5:5
|
||||||
|
|
|
|
||||||
LL | use main as x;
|
LL | use main as x;
|
||||||
| ----^^^^^
|
| ^^^^^^^^^ no `main` in the root
|
||||||
| |
|
|
||||||
| no `main` in the root
|
|
||||||
| help: a similar name exists in the module: `main`
|
|
||||||
|
|
||||||
error[E0432]: unresolved import `test`
|
error[E0432]: unresolved import `test`
|
||||||
--> $DIR/inaccessible-test-modules.rs:6:5
|
--> $DIR/inaccessible-test-modules.rs:6:5
|
||||||
|
@ -13,14 +10,10 @@ error[E0432]: unresolved import `test`
|
||||||
LL | use test as y;
|
LL | use test as y;
|
||||||
| ^^^^^^^^^ no `test` in the root
|
| ^^^^^^^^^ no `test` in the root
|
||||||
|
|
|
|
||||||
help: a similar name exists in the module
|
|
||||||
|
|
|
||||||
LL | use test as y;
|
|
||||||
| ~~~~
|
|
||||||
help: consider importing this module instead
|
help: consider importing this module instead
|
||||||
|
|
|
|
||||||
LL | use test::test;
|
LL | use test::test as y;
|
||||||
| ~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,69 @@
|
||||||
// known-bug
|
// check-pass
|
||||||
|
|
||||||
|
// This test checks that we're correctly dealing with inductive cycles
|
||||||
|
// with canonical inference variables.
|
||||||
|
|
||||||
// This should compile but fails with the current solver.
|
|
||||||
//
|
|
||||||
// This checks that the new solver uses `Ambiguous` when hitting the
|
|
||||||
// inductive cycle here when proving `exists<^0, ^1> (): Trait<^0, ^1>`
|
|
||||||
// which requires proving `Trait<?1, ?0>` but that has the same
|
|
||||||
// canonical representation.
|
|
||||||
trait Trait<T, U> {}
|
trait Trait<T, U> {}
|
||||||
|
|
||||||
impl<T, U> Trait<T, U> for ()
|
trait IsNotU32 {}
|
||||||
|
impl IsNotU32 for i32 {}
|
||||||
|
impl<T: IsNotU32, U> Trait<T, U> for () // impl 1
|
||||||
where
|
where
|
||||||
(): Trait<U, T>,
|
(): Trait<U, T>
|
||||||
T: OtherTrait,
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
trait OtherTrait {}
|
impl<T> Trait<u32, T> for () {} // impl 2
|
||||||
impl OtherTrait for u32 {}
|
|
||||||
|
|
||||||
fn require_trait<T, U>()
|
// If we now check whether `(): Trait<?0, ?1>` holds this has to
|
||||||
|
// result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>`
|
||||||
|
// applies. The remainder of this test asserts that.
|
||||||
|
|
||||||
|
// If we were to error on inductive cycles with canonical inference variables
|
||||||
|
// this would be wrong:
|
||||||
|
|
||||||
|
// (): Trait<?0, ?1>
|
||||||
|
// - impl 1
|
||||||
|
// - ?0: IsNotU32 // ambig
|
||||||
|
// - (): Trait<?1, ?0> // canonical cycle -> err
|
||||||
|
// - ERR
|
||||||
|
// - impl 2
|
||||||
|
// - OK ?0 == u32
|
||||||
|
//
|
||||||
|
// Result: OK ?0 == u32.
|
||||||
|
|
||||||
|
// (): Trait<i32, u32>
|
||||||
|
// - impl 1
|
||||||
|
// - i32: IsNotU32 // ok
|
||||||
|
// - (): Trait<u32, i32>
|
||||||
|
// - impl 1
|
||||||
|
// - u32: IsNotU32 // err
|
||||||
|
// - ERR
|
||||||
|
// - impl 2
|
||||||
|
// - OK
|
||||||
|
// - OK
|
||||||
|
// - impl 2 (trivial ERR)
|
||||||
|
//
|
||||||
|
// Result OK
|
||||||
|
|
||||||
|
// This would mean that `(): Trait<?0, ?1>` is not complete,
|
||||||
|
// which is unsound if we're in coherence.
|
||||||
|
|
||||||
|
fn implements_trait<T, U>() -> (T, U)
|
||||||
where
|
where
|
||||||
(): Trait<T, U>
|
(): Trait<T, U>,
|
||||||
{}
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A hack to only constrain the infer vars after first checking
|
||||||
|
// the `(): Trait<_, _>`.
|
||||||
|
trait Constrain<T> {}
|
||||||
|
impl<T> Constrain<T> for T {}
|
||||||
|
fn constrain<T: Constrain<U>, U>(_: U) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
require_trait::<_, _>();
|
let (x, y) = implements_trait::<_, _>();
|
||||||
//~^ ERROR overflow evaluating
|
|
||||||
|
constrain::<i32, _>(x);
|
||||||
|
constrain::<u32, _>(y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
error[E0275]: overflow evaluating the requirement `_: Sized`
|
|
||||||
--> $DIR/inductive-canonical-cycle.rs:26:5
|
|
||||||
|
|
|
||||||
LL | require_trait::<_, _>();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_canonical_cycle`)
|
|
||||||
note: required for `()` to implement `Trait<_, _>`
|
|
||||||
--> $DIR/inductive-canonical-cycle.rs:11:12
|
|
||||||
|
|
|
||||||
LL | impl<T, U> Trait<T, U> for ()
|
|
||||||
| ^^^^^^^^^^^ ^^
|
|
||||||
= note: 128 redundant requirements hidden
|
|
||||||
= note: required for `()` to implement `Trait<_, _>`
|
|
||||||
note: required by a bound in `require_trait`
|
|
||||||
--> $DIR/inductive-canonical-cycle.rs:22:9
|
|
||||||
|
|
|
||||||
LL | fn require_trait<T, U>()
|
|
||||||
| ------------- required by a bound in this
|
|
||||||
LL | where
|
|
||||||
LL | (): Trait<T, U>
|
|
||||||
| ^^^^^^^^^^^ required by this bound in `require_trait`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
|
|
@ -185,7 +185,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
|
||||||
// explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the
|
// explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the
|
||||||
// bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host
|
// bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host
|
||||||
// builds.
|
// builds.
|
||||||
cmd.env("RUSTC", &fs::canonicalize(find_miri()).unwrap());
|
cmd.env("RUSTC", fs::canonicalize(find_miri()).unwrap());
|
||||||
cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases!
|
cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases!
|
||||||
|
|
||||||
// Set rustdoc to us as well, so we can run doctests.
|
// Set rustdoc to us as well, so we can run doctests.
|
||||||
|
|
|
@ -108,7 +108,8 @@ case $HOST_TARGET in
|
||||||
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
|
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
|
||||||
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
|
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
|
||||||
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
|
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
|
||||||
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer
|
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings
|
||||||
|
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings
|
||||||
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
|
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
|
||||||
MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file
|
MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
4f4d0586ad20c66a16d547581ca379beafece93a
|
c54c8cbac882e149e04a9e1f2d146fd548ae30ae
|
||||||
|
|
|
@ -88,11 +88,7 @@ impl fmt::Display for InvalidationCause {
|
||||||
match self {
|
match self {
|
||||||
InvalidationCause::Access(kind) => write!(f, "{kind}"),
|
InvalidationCause::Access(kind) => write!(f, "{kind}"),
|
||||||
InvalidationCause::Retag(perm, kind) =>
|
InvalidationCause::Retag(perm, kind) =>
|
||||||
if *kind == RetagCause::FnEntry {
|
write!(f, "{perm:?} {retag}", retag = kind.summary()),
|
||||||
write!(f, "{perm:?} FnEntry retag")
|
|
||||||
} else {
|
|
||||||
write!(f, "{perm:?} retag")
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +189,7 @@ struct RetagOp {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum RetagCause {
|
pub enum RetagCause {
|
||||||
Normal,
|
Normal,
|
||||||
FnReturn,
|
FnReturnPlace,
|
||||||
FnEntry,
|
FnEntry,
|
||||||
TwoPhase,
|
TwoPhase,
|
||||||
}
|
}
|
||||||
|
@ -495,8 +491,8 @@ impl RetagCause {
|
||||||
fn summary(&self) -> String {
|
fn summary(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
RetagCause::Normal => "retag",
|
RetagCause::Normal => "retag",
|
||||||
RetagCause::FnEntry => "FnEntry retag",
|
RetagCause::FnEntry => "function-entry retag",
|
||||||
RetagCause::FnReturn => "FnReturn retag",
|
RetagCause::FnReturnPlace => "return-place retag",
|
||||||
RetagCause::TwoPhase => "two-phase retag",
|
RetagCause::TwoPhase => "two-phase retag",
|
||||||
}
|
}
|
||||||
.to_string()
|
.to_string()
|
||||||
|
|
|
@ -998,7 +998,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
access: Some(AccessKind::Write),
|
access: Some(AccessKind::Write),
|
||||||
protector: Some(ProtectorKind::StrongProtector),
|
protector: Some(ProtectorKind::StrongProtector),
|
||||||
};
|
};
|
||||||
let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
|
let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?;
|
||||||
// And use reborrowed pointer for return place.
|
// And use reborrowed pointer for return place.
|
||||||
let return_place = this.ref_to_mplace(&val)?;
|
let return_place = this.ref_to_mplace(&val)?;
|
||||||
this.frame_mut().return_place = return_place.into();
|
this.frame_mut().return_place = return_place.into();
|
||||||
|
|
|
@ -943,7 +943,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
link_name: Symbol,
|
link_name: Symbol,
|
||||||
) -> InterpResult<'tcx, ()> {
|
) -> InterpResult<'tcx, ()> {
|
||||||
self.check_abi(abi, exp_abi)?;
|
self.check_abi(abi, exp_abi)?;
|
||||||
if let Some((body, _)) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
|
if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
|
||||||
|
// If compiler-builtins is providing the symbol, then don't treat it as a clash.
|
||||||
|
// We'll use our built-in implementation in `emulate_foreign_item_by_name` for increased
|
||||||
|
// performance. Note that this means we won't catch any undefined behavior in
|
||||||
|
// compiler-builtins when running other crates, but Miri can still be run on
|
||||||
|
// compiler-builtins itself (or any crate that uses it as a normal dependency)
|
||||||
|
if self.eval_context_ref().tcx.is_compiler_builtins(instance.def_id().krate) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
|
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
|
||||||
link_name,
|
link_name,
|
||||||
span: body.span.data(),
|
span: body.span.data(),
|
||||||
|
|
|
@ -219,7 +219,6 @@ mod tests {
|
||||||
/// Query the map at every offset in the range and collect the results.
|
/// Query the map at every offset in the range and collect the results.
|
||||||
fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
|
fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
|
||||||
(offset..offset + len)
|
(offset..offset + len)
|
||||||
.into_iter()
|
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
map.iter(Size::from_bytes(i), Size::from_bytes(1)).next().map(|(_, &t)| t).unwrap()
|
map.iter(Size::from_bytes(i), Size::from_bytes(1)).next().map(|(_, &t)| t).unwrap()
|
||||||
})
|
})
|
||||||
|
|
|
@ -166,7 +166,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
// `buf_size` represents the size in characters.
|
// `buf_size` represents the size in characters.
|
||||||
let buf_size = u64::from(this.read_scalar(size_op)?.to_u32()?);
|
let buf_size = u64::from(this.read_scalar(size_op)?.to_u32()?);
|
||||||
Scalar::from_u32(windows_check_buffer_size(
|
Scalar::from_u32(windows_check_buffer_size(
|
||||||
this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?,
|
this.write_os_str_to_wide_str(
|
||||||
|
&var, buf_ptr, buf_size, /*truncate*/ false,
|
||||||
|
)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -366,7 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
match env::current_dir() {
|
match env::current_dir() {
|
||||||
Ok(cwd) =>
|
Ok(cwd) =>
|
||||||
return Ok(Scalar::from_u32(windows_check_buffer_size(
|
return Ok(Scalar::from_u32(windows_check_buffer_size(
|
||||||
this.write_path_to_wide_str(&cwd, buf, size)?,
|
this.write_path_to_wide_str(&cwd, buf, size, /*truncate*/ false)?,
|
||||||
))),
|
))),
|
||||||
Err(e) => this.set_last_error_from_io_error(e.kind())?,
|
Err(e) => this.set_last_error_from_io_error(e.kind())?,
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,17 +101,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
self.eval_context_mut().write_c_str(bytes, ptr, size)
|
self.eval_context_mut().write_c_str(bytes, ptr, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
|
/// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what the
|
||||||
/// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
|
/// Windows APIs usually handle.
|
||||||
/// to write if `size` is not large enough to fit the contents of `os_string` plus a null
|
///
|
||||||
/// terminator. It returns `Ok((true, length))` if the writing process was successful. The
|
/// If `truncate == false` (the usual mode of operation), this function returns `Ok((false,
|
||||||
/// string length returned does include the null terminator. Length is measured in units of
|
/// length))` without trying to write if `size` is not large enough to fit the contents of
|
||||||
/// `u16.`
|
/// `os_string` plus a null terminator. It returns `Ok((true, length))` if the writing process
|
||||||
|
/// was successful. The string length returned does include the null terminator. Length is
|
||||||
|
/// measured in units of `u16.`
|
||||||
|
///
|
||||||
|
/// If `truncate == true`, then in case `size` is not large enough it *will* write the first
|
||||||
|
/// `size.saturating_sub(1)` many items, followed by a null terminator (if `size > 0`).
|
||||||
fn write_os_str_to_wide_str(
|
fn write_os_str_to_wide_str(
|
||||||
&mut self,
|
&mut self,
|
||||||
os_str: &OsStr,
|
os_str: &OsStr,
|
||||||
ptr: Pointer<Option<Provenance>>,
|
ptr: Pointer<Option<Provenance>>,
|
||||||
size: u64,
|
size: u64,
|
||||||
|
truncate: bool,
|
||||||
) -> InterpResult<'tcx, (bool, u64)> {
|
) -> InterpResult<'tcx, (bool, u64)> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
|
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
|
||||||
|
@ -129,7 +135,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let u16_vec = os_str_to_u16vec(os_str)?;
|
let u16_vec = os_str_to_u16vec(os_str)?;
|
||||||
self.eval_context_mut().write_wide_str(&u16_vec, ptr, size)
|
let (written, size_needed) = self.eval_context_mut().write_wide_str(&u16_vec, ptr, size)?;
|
||||||
|
if truncate && !written && size > 0 {
|
||||||
|
// Write the truncated part that fits.
|
||||||
|
let truncated_data = &u16_vec[..size.saturating_sub(1).try_into().unwrap()];
|
||||||
|
let (written, written_len) =
|
||||||
|
self.eval_context_mut().write_wide_str(truncated_data, ptr, size)?;
|
||||||
|
assert!(written && written_len == size);
|
||||||
|
}
|
||||||
|
Ok((written, size_needed))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes.
|
/// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes.
|
||||||
|
@ -143,7 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
|
|
||||||
let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
|
let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
|
||||||
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
|
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
|
||||||
assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0);
|
let (written, _) = self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap();
|
||||||
|
assert!(written);
|
||||||
Ok(arg_place.ptr)
|
Ok(arg_place.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +173,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
|
|
||||||
let arg_type = this.tcx.mk_array(this.tcx.types.u16, size);
|
let arg_type = this.tcx.mk_array(this.tcx.types.u16, size);
|
||||||
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
|
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
|
||||||
assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0);
|
let (written, _) =
|
||||||
|
self.write_os_str_to_wide_str(os_str, arg_place.ptr, size, /*truncate*/ false).unwrap();
|
||||||
|
assert!(written);
|
||||||
Ok(arg_place.ptr)
|
Ok(arg_place.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,11 +229,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
path: &Path,
|
path: &Path,
|
||||||
ptr: Pointer<Option<Provenance>>,
|
ptr: Pointer<Option<Provenance>>,
|
||||||
size: u64,
|
size: u64,
|
||||||
|
truncate: bool,
|
||||||
) -> InterpResult<'tcx, (bool, u64)> {
|
) -> InterpResult<'tcx, (bool, u64)> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let os_str =
|
let os_str =
|
||||||
this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
|
this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
|
||||||
this.write_os_str_to_wide_str(&os_str, ptr, size)
|
this.write_os_str_to_wide_str(&os_str, ptr, size, truncate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate enough memory to store a Path as a null-terminated sequence of bytes,
|
/// Allocate enough memory to store a Path as a null-terminated sequence of bytes,
|
||||||
|
@ -232,6 +250,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
this.alloc_os_str_as_c_str(&os_str, memkind)
|
this.alloc_os_str_as_c_str(&os_str, memkind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocate enough memory to store a Path as a null-terminated sequence of `u16`s,
|
||||||
|
/// adjusting path separators if needed.
|
||||||
|
fn alloc_path_as_wide_str(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
memkind: MemoryKind<MiriMemoryKind>,
|
||||||
|
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
let os_str =
|
||||||
|
this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
|
||||||
|
this.alloc_os_str_as_wide_str(&os_str, memkind)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::get_first)]
|
#[allow(clippy::get_first)]
|
||||||
fn convert_path<'a>(
|
fn convert_path<'a>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -381,6 +381,46 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
|
|
||||||
this.write_scalar(Scalar::from_u32(1), dest)?;
|
this.write_scalar(Scalar::from_u32(1), dest)?;
|
||||||
}
|
}
|
||||||
|
"GetModuleFileNameW" => {
|
||||||
|
let [handle, filename, size] =
|
||||||
|
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
|
||||||
|
this.check_no_isolation("`GetModuleFileNameW`")?;
|
||||||
|
|
||||||
|
let handle = this.read_machine_usize(handle)?;
|
||||||
|
let filename = this.read_pointer(filename)?;
|
||||||
|
let size = this.read_scalar(size)?.to_u32()?;
|
||||||
|
|
||||||
|
if handle != 0 {
|
||||||
|
throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using the host current_exe is a bit off, but consistent with Linux
|
||||||
|
// (where stdlib reads /proc/self/exe).
|
||||||
|
// Unfortunately this Windows function has a crazy behavior so we can't just use
|
||||||
|
// `write_path_to_wide_str`...
|
||||||
|
let path = std::env::current_exe().unwrap();
|
||||||
|
let (all_written, size_needed) = this.write_path_to_wide_str(
|
||||||
|
&path,
|
||||||
|
filename,
|
||||||
|
size.into(),
|
||||||
|
/*truncate*/ true,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if all_written {
|
||||||
|
// If the function succeeds, the return value is the length of the string that
|
||||||
|
// is copied to the buffer, in characters, not including the terminating null
|
||||||
|
// character.
|
||||||
|
this.write_int(size_needed.checked_sub(1).unwrap(), dest)?;
|
||||||
|
} else {
|
||||||
|
// If the buffer is too small to hold the module name, the string is truncated
|
||||||
|
// to nSize characters including the terminating null character, the function
|
||||||
|
// returns nSize, and the function sets the last error to
|
||||||
|
// ERROR_INSUFFICIENT_BUFFER.
|
||||||
|
this.write_int(size, dest)?;
|
||||||
|
let insufficient_buffer = this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER");
|
||||||
|
this.set_last_error(insufficient_buffer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Threading
|
// Threading
|
||||||
"CreateThread" => {
|
"CreateThread" => {
|
||||||
|
|
|
@ -14,6 +14,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -44,8 +50,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -57,6 +65,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.139"
|
||||||
|
@ -123,6 +140,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "page_size"
|
name = "page_size"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -269,9 +292,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.23.0"
|
version = "1.23.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
checksum = "38a54aca0c15d014013256222ba0ebed095673f89345dd79119d912eb561b7a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -316,6 +339,60 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -13,11 +13,11 @@ libc = "0.2"
|
||||||
num_cpus = "1.10.1"
|
num_cpus = "1.10.1"
|
||||||
|
|
||||||
getrandom_1 = { package = "getrandom", version = "0.1" }
|
getrandom_1 = { package = "getrandom", version = "0.1" }
|
||||||
getrandom = { version = "0.2" }
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
rand = { version = "0.8", features = ["small_rng"] }
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies]
|
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies]
|
||||||
page_size = "0.5"
|
page_size = "0.5"
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.23", features = ["full"] }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
|
@ -5,7 +5,7 @@ LL | pub fn safe(_x: &mut i32, _y: &i32) {}
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
| this error occurs as part of FnEntry retag at ALLOC[0x0..0x4]
|
| this error occurs as part of function-entry retag at ALLOC[0x0..0x4]
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
|
@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
|
||||||
|
|
|
|
||||||
LL | safe_raw(xraw, xshr);
|
LL | safe_raw(xraw, xshr);
|
||||||
| ^^^^
|
| ^^^^
|
||||||
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call
|
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call
|
||||||
--> $DIR/aliasing_mut3.rs:LL:CC
|
--> $DIR/aliasing_mut3.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | safe_raw(xraw, xshr);
|
LL | safe_raw(xraw, xshr);
|
||||||
|
|
|
@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
|
||||||
|
|
|
|
||||||
LL | let z = &mut x as *mut i32;
|
LL | let z = &mut x as *mut i32;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call
|
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call
|
||||||
--> $DIR/fnentry_invalidation.rs:LL:CC
|
--> $DIR/fnentry_invalidation.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | x.do_bad();
|
LL | x.do_bad();
|
||||||
|
|
|
@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0xc]
|
||||||
|
|
|
|
||||||
LL | let ptr = t.sli.as_ptr();
|
LL | let ptr = t.sli.as_ptr();
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry retag inside this call
|
help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique function-entry retag inside this call
|
||||||
--> $DIR/fnentry_invalidation2.rs:LL:CC
|
--> $DIR/fnentry_invalidation2.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | let _ = t.sli.as_mut_ptr();
|
LL | let _ = t.sli.as_mut_ptr();
|
||||||
|
|
|
@ -186,8 +186,65 @@ fn join_orders_after_tls_destructors() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dtors_in_dtors_in_dtors() {
|
||||||
|
use std::cell::UnsafeCell;
|
||||||
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
struct Signal(Arc<(Mutex<bool>, Condvar)>);
|
||||||
|
|
||||||
|
impl Signal {
|
||||||
|
fn notify(&self) {
|
||||||
|
let (set, cvar) = &*self.0;
|
||||||
|
*set.lock().unwrap() = true;
|
||||||
|
cvar.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait(&self) {
|
||||||
|
let (set, cvar) = &*self.0;
|
||||||
|
let mut set = set.lock().unwrap();
|
||||||
|
while !*set {
|
||||||
|
set = cvar.wait(set).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotifyOnDrop(Signal);
|
||||||
|
|
||||||
|
impl Drop for NotifyOnDrop {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let NotifyOnDrop(ref f) = *self;
|
||||||
|
f.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S1(Signal);
|
||||||
|
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
|
||||||
|
thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None));
|
||||||
|
|
||||||
|
impl Drop for S1 {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let S1(ref signal) = *self;
|
||||||
|
unsafe {
|
||||||
|
let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let signal = Signal::default();
|
||||||
|
let signal2 = signal.clone();
|
||||||
|
let _t = thread::spawn(move || unsafe {
|
||||||
|
let mut signal = Some(signal2);
|
||||||
|
K1.with(|s| *s.get() = Some(S1(signal.take().unwrap())));
|
||||||
|
});
|
||||||
|
// Note that this test will deadlock if TLS destructors aren't run (this
|
||||||
|
// requires the destructor to be run to pass the test).
|
||||||
|
signal.wait();
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
check_destructors();
|
check_destructors();
|
||||||
check_blocking();
|
check_blocking();
|
||||||
join_orders_after_tls_destructors();
|
join_orders_after_tls_destructors();
|
||||||
|
dtors_in_dtors_in_dtors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
//@ignore-target-windows: current_exe not supported on Windows
|
|
||||||
//@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target
|
//@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target
|
||||||
//@compile-flags: -Zmiri-disable-isolation
|
//@compile-flags: -Zmiri-disable-isolation
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue