mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-07 13:25:45 +00:00
Auto merge of #133377 - jieyouxu:rollup-n536hzq, r=jieyouxu
Rollup of 6 pull requests Successful merges: - #127483 (Allow disabling ASan instrumentation for globals) - #131505 (use `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)` as a `TMPDIR` fallback on Darwin) - #132949 (Add specific diagnostic for using macro_rules macro as attribute/derive) - #133286 (Re-delay a resolve `bug` related to `Self`-ctor in patterns) - #133332 (Mark `<[T; N]>::as_mut_slice` with the `const` specifier.) - #133366 (Remove unnecessary bool from `ExpectedFound::new`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
826b673412
@ -172,3 +172,12 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
|
||||
Visibility::Protected => llvm::Visibility::Protected,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) {
|
||||
if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) {
|
||||
unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) };
|
||||
}
|
||||
if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) {
|
||||
unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) };
|
||||
}
|
||||
}
|
||||
|
@ -470,6 +470,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||
base::set_link_section(g, attrs);
|
||||
}
|
||||
|
||||
base::set_variable_sanitizer_attrs(g, attrs);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
|
@ -2460,4 +2460,7 @@ unsafe extern "C" {
|
||||
pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
|
||||
pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
|
||||
pub fn LLVMRustSetNoSanitizeAddress(Global: &Value);
|
||||
pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let can_coerce = self.may_coerce(arg_ty, coerced_ty);
|
||||
if !can_coerce {
|
||||
return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
|
||||
ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
|
||||
ty::error::ExpectedFound::new(coerced_ty, arg_ty),
|
||||
)));
|
||||
}
|
||||
|
||||
@ -758,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
expected_ty
|
||||
};
|
||||
TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty)
|
||||
TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
|
||||
};
|
||||
|
||||
// The algorithm here is inspired by levenshtein distance and longest common subsequence.
|
||||
|
@ -308,17 +308,14 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Regions(ExpectedFound::new(true, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::Regions(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +323,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,13 +334,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
|
||||
cause: cause.clone(),
|
||||
values: match (a.unpack(), b.unpack()) {
|
||||
(GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
|
||||
ValuePairs::Regions(ExpectedFound::new(true, a, b))
|
||||
ValuePairs::Regions(ExpectedFound::new(a, b))
|
||||
}
|
||||
(GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
|
||||
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
|
||||
ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
|
||||
}
|
||||
(GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
|
||||
ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into()))
|
||||
ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
|
||||
}
|
||||
_ => bug!("relating different kinds: {a:?} {b:?}"),
|
||||
},
|
||||
@ -353,19 +350,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(true, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::Terms(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::TraitRefs(ExpectedFound::new(true, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,17 +364,14 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Aliases(ExpectedFound::new(true, a.into(), b.into())),
|
||||
values: ValuePairs::Aliases(ExpectedFound::new(a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Aliases(ExpectedFound::new(true, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::Aliases(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,7 +380,6 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::PolySigs(ExpectedFound::new(
|
||||
true,
|
||||
ty::Binder::dummy(a),
|
||||
ty::Binder::dummy(b),
|
||||
)),
|
||||
@ -402,10 +389,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
|
||||
|
||||
impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::PolySigs(ExpectedFound::new(true, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +397,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(true, a, b)),
|
||||
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -422,7 +406,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
|
||||
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::ExistentialProjection(ExpectedFound::new(true, a, b)),
|
||||
values: ValuePairs::ExistentialProjection(ExpectedFound::new(a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1478,39 +1478,29 @@ impl<'tcx> TypeTrace<'tcx> {
|
||||
self.cause.span
|
||||
}
|
||||
|
||||
pub fn types(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
) -> TypeTrace<'tcx> {
|
||||
pub fn types(cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trait_refs(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: ty::TraitRef<'tcx>,
|
||||
b: ty::TraitRef<'tcx>,
|
||||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
|
||||
}
|
||||
|
||||
pub fn consts(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
a: ty::Const<'tcx>,
|
||||
b: ty::Const<'tcx>,
|
||||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
res
|
||||
} else {
|
||||
let (a, b) = self.resolve_vars_if_possible((a, b));
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2051,6 +2051,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
|
||||
return llvm::compression::zstd::isAvailable();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) {
|
||||
GlobalValue &GV = *unwrap<GlobalValue>(Global);
|
||||
GlobalValue::SanitizerMetadata MD;
|
||||
if (GV.hasSanitizerMetadata())
|
||||
MD = GV.getSanitizerMetadata();
|
||||
MD.NoAddress = true;
|
||||
MD.IsDynInit = false;
|
||||
GV.setSanitizerMetadata(MD);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
|
||||
GlobalValue &GV = *unwrap<GlobalValue>(Global);
|
||||
GlobalValue::SanitizerMetadata MD;
|
||||
if (GV.hasSanitizerMetadata())
|
||||
MD = GV.getSanitizerMetadata();
|
||||
MD.NoHWAddress = true;
|
||||
GV.setSanitizerMetadata(MD);
|
||||
}
|
||||
|
||||
// Operations on composite constants.
|
||||
// These are clones of LLVM api functions that will become available in future
|
||||
// releases. They can be removed once Rust's minimum supported LLVM version
|
||||
|
@ -92,7 +92,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
|
||||
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||
b_v.dedup();
|
||||
if a_v.len() != b_v.len() {
|
||||
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b)));
|
||||
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
|
||||
}
|
||||
|
||||
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
|
||||
@ -112,7 +112,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
|
||||
ty::ExistentialPredicate::AutoTrait(a),
|
||||
ty::ExistentialPredicate::AutoTrait(b),
|
||||
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
|
||||
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))),
|
||||
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
|
||||
}
|
||||
});
|
||||
tcx.mk_poly_existential_predicates_from_iter(v)
|
||||
|
@ -558,6 +558,10 @@ passes_no_mangle_foreign =
|
||||
passes_no_patterns =
|
||||
patterns not allowed in naked function parameters
|
||||
|
||||
passes_no_sanitize =
|
||||
`#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
|
||||
.label = not {$accepted_kind}
|
||||
|
||||
passes_non_exported_macro_invalid_attrs =
|
||||
attribute should be applied to function or closure
|
||||
.label = not a function or closure
|
||||
|
@ -126,9 +126,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
|
||||
[sym::coverage, ..] => self.check_coverage(attr, span, target),
|
||||
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
|
||||
[sym::no_sanitize, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||
}
|
||||
[sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target),
|
||||
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
|
||||
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
|
||||
[sym::target_feature, ..] => {
|
||||
@ -450,6 +448,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
let sym = item.name_or_empty();
|
||||
match sym {
|
||||
sym::address | sym::hwaddress => {
|
||||
let is_valid =
|
||||
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
|
||||
if !is_valid {
|
||||
self.dcx().emit_err(errors::NoSanitize {
|
||||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function or static",
|
||||
attr_str: sym.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let is_valid = matches!(target, Target::Fn | Target::Method(..));
|
||||
if !is_valid {
|
||||
self.dcx().emit_err(errors::NoSanitize {
|
||||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function",
|
||||
attr_str: sym.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_generic_attr(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
|
@ -1846,3 +1846,14 @@ pub(crate) struct AttrCrateLevelOnlySugg {
|
||||
#[primary_span]
|
||||
pub attr: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_no_sanitize)]
|
||||
pub(crate) struct NoSanitize<'a> {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub defn_span: Span,
|
||||
pub accepted_kind: &'a str,
|
||||
pub attr_str: &'a str,
|
||||
}
|
||||
|
@ -257,8 +257,14 @@ resolve_lowercase_self =
|
||||
attempt to use a non-constant value in a constant
|
||||
.suggestion = try using `Self`
|
||||
|
||||
resolve_macro_cannot_use_as_attr =
|
||||
`{$ident}` exists, but a declarative macro cannot be used as an attribute macro
|
||||
|
||||
resolve_macro_cannot_use_as_derive =
|
||||
`{$ident}` exists, but a declarative macro cannot be used as a derive macro
|
||||
|
||||
resolve_macro_defined_later =
|
||||
a macro with the same name exists, but it appears later at here
|
||||
a macro with the same name exists, but it appears later
|
||||
|
||||
resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments =
|
||||
macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||
|
@ -35,7 +35,8 @@ use tracing::debug;
|
||||
|
||||
use crate::errors::{
|
||||
self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
|
||||
ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName,
|
||||
ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
|
||||
MaybeMissingMacroRulesName,
|
||||
};
|
||||
use crate::imports::{Import, ImportKind};
|
||||
use crate::late::{PatternSource, Rib};
|
||||
@ -1473,8 +1474,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
let scope = self.local_macro_def_scopes[&def_id];
|
||||
let parent_nearest = parent_scope.module.nearest_parent_mod();
|
||||
if Some(parent_nearest) == scope.opt_def_id() {
|
||||
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
|
||||
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
|
||||
match macro_kind {
|
||||
MacroKind::Bang => {
|
||||
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
|
||||
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
|
||||
}
|
||||
MacroKind::Attr => {
|
||||
err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
|
||||
}
|
||||
MacroKind::Derive => {
|
||||
err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -665,6 +665,22 @@ pub(crate) struct MacroSuggMovePosition {
|
||||
pub(crate) ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum MacroRulesNot {
|
||||
#[label(resolve_macro_cannot_use_as_attr)]
|
||||
Attr {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
},
|
||||
#[label(resolve_macro_cannot_use_as_derive)]
|
||||
Derive {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(resolve_missing_macro_rules_name)]
|
||||
pub(crate) struct MaybeMissingMacroRulesName {
|
||||
|
@ -3940,12 +3940,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||
}
|
||||
Res::SelfCtor(_) => {
|
||||
// We resolve `Self` in pattern position as an ident sometimes during recovery,
|
||||
// so delay a bug instead of ICEing. (Note: is this no longer true? We now ICE. If
|
||||
// this triggers, please convert to a delayed bug and add a test.)
|
||||
self.r.dcx().span_bug(
|
||||
// so delay a bug instead of ICEing.
|
||||
self.r.dcx().span_delayed_bug(
|
||||
ident.span,
|
||||
"unexpected `SelfCtor` in pattern, expected identifier"
|
||||
);
|
||||
None
|
||||
}
|
||||
_ => span_bug!(
|
||||
ident.span,
|
||||
|
@ -152,7 +152,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::types(cause, true, expected, actual),
|
||||
TypeTrace::types(cause, expected, actual),
|
||||
param_env,
|
||||
err,
|
||||
)
|
||||
@ -167,7 +167,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::consts(cause, true, expected, actual),
|
||||
TypeTrace::consts(cause, expected, actual),
|
||||
param_env,
|
||||
err,
|
||||
)
|
||||
|
@ -725,7 +725,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
&obligation.cause,
|
||||
None,
|
||||
None,
|
||||
TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)),
|
||||
TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),
|
||||
false,
|
||||
);
|
||||
diag
|
||||
@ -1449,7 +1449,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
secondary_span,
|
||||
values.map(|(_, normalized_ty, expected_ty)| {
|
||||
obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new(
|
||||
true,
|
||||
expected_ty,
|
||||
normalized_ty,
|
||||
)))
|
||||
@ -2755,7 +2754,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
(obligation.cause.clone(), terr)
|
||||
};
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
|
||||
TypeTrace::trait_refs(&cause, expected_trait_ref, found_trait_ref),
|
||||
obligation.param_env,
|
||||
terr,
|
||||
)
|
||||
@ -2846,7 +2845,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
|
||||
{
|
||||
return Ok(self.report_and_explain_type_error(
|
||||
TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref),
|
||||
TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
|
||||
obligation.param_env,
|
||||
ty::error::TypeError::Mismatch,
|
||||
));
|
||||
|
@ -264,14 +264,14 @@ fn fulfillment_error_for_no_solution<'tcx>(
|
||||
let (a, b) = infcx.enter_forall_and_leak_universe(
|
||||
obligation.predicate.kind().rebind((pred.a, pred.b)),
|
||||
);
|
||||
let expected_found = ExpectedFound::new(true, a, b);
|
||||
let expected_found = ExpectedFound::new(a, b);
|
||||
FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
|
||||
}
|
||||
ty::PredicateKind::Coerce(pred) => {
|
||||
let (a, b) = infcx.enter_forall_and_leak_universe(
|
||||
obligation.predicate.kind().rebind((pred.a, pred.b)),
|
||||
);
|
||||
let expected_found = ExpectedFound::new(false, a, b);
|
||||
let expected_found = ExpectedFound::new(b, a);
|
||||
FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
|
||||
}
|
||||
ty::PredicateKind::Clause(_)
|
||||
|
@ -557,8 +557,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
ProcessResult::Changed(mk_pending(ok.obligations))
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
let expected_found =
|
||||
ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b);
|
||||
let expected_found = if subtype.a_is_expected {
|
||||
ExpectedFound::new(subtype.a, subtype.b)
|
||||
} else {
|
||||
ExpectedFound::new(subtype.b, subtype.a)
|
||||
};
|
||||
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
|
||||
}
|
||||
}
|
||||
@ -578,7 +581,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
}
|
||||
Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
|
||||
Ok(Err(err)) => {
|
||||
let expected_found = ExpectedFound::new(false, coerce.a, coerce.b);
|
||||
let expected_found = ExpectedFound::new(coerce.b, coerce.a);
|
||||
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
|
||||
}
|
||||
}
|
||||
@ -703,7 +706,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
}
|
||||
Err(err) => {
|
||||
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
|
||||
ExpectedFound::new(true, c1, c2),
|
||||
ExpectedFound::new(c1, c2),
|
||||
err,
|
||||
))
|
||||
}
|
||||
@ -727,7 +730,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
ProcessResult::Unchanged
|
||||
} else {
|
||||
// Two different constants using generic parameters ~> error.
|
||||
let expected_found = ExpectedFound::new(true, c1, c2);
|
||||
let expected_found = ExpectedFound::new(c1, c2);
|
||||
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
|
||||
expected_found,
|
||||
TypeError::ConstMismatch(expected_found),
|
||||
|
@ -70,7 +70,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
|
||||
) => Ok(a),
|
||||
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
|
||||
}
|
||||
|
||||
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)),
|
||||
@ -95,7 +95,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
|
||||
}
|
||||
|
||||
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
||||
return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b)));
|
||||
return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b)));
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
@ -12,12 +12,8 @@ pub struct ExpectedFound<T> {
|
||||
}
|
||||
|
||||
impl<T> ExpectedFound<T> {
|
||||
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
|
||||
if a_is_expected {
|
||||
ExpectedFound { expected: a, found: b }
|
||||
} else {
|
||||
ExpectedFound { expected: b, found: a }
|
||||
}
|
||||
pub fn new(expected: T, found: T) -> Self {
|
||||
ExpectedFound { expected, found }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,16 +171,16 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
|
||||
return Err(TypeError::VariadicMismatch({
|
||||
let a = a.c_variadic;
|
||||
let b = b.c_variadic;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}));
|
||||
}
|
||||
|
||||
if a.safety != b.safety {
|
||||
return Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a.safety, b.safety)));
|
||||
return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety, b.safety)));
|
||||
}
|
||||
|
||||
if a.abi != b.abi {
|
||||
return Err(TypeError::AbiMismatch(ExpectedFound::new(true, a.abi, b.abi)));
|
||||
return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi, b.abi)));
|
||||
};
|
||||
|
||||
let a_inputs = a.inputs();
|
||||
@ -233,7 +233,7 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
|
||||
Err(TypeError::ProjectionMismatched({
|
||||
let a = a.def_id;
|
||||
let b = b.def_id;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}))
|
||||
} else {
|
||||
let args = match a.kind(relation.cx()) {
|
||||
@ -274,7 +274,7 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
|
||||
Err(TypeError::ProjectionMismatched({
|
||||
let a = a.def_id;
|
||||
let b = b.def_id;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}))
|
||||
} else {
|
||||
let args = match a.kind(relation.cx()) {
|
||||
@ -309,7 +309,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
|
||||
Err(TypeError::ProjectionMismatched({
|
||||
let a = a.def_id;
|
||||
let b = b.def_id;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}))
|
||||
} else {
|
||||
let term = relation.relate_with_variance(
|
||||
@ -340,7 +340,7 @@ impl<I: Interner> Relate<I> for ty::TraitRef<I> {
|
||||
Err(TypeError::Traits({
|
||||
let a = a.def_id;
|
||||
let b = b.def_id;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}))
|
||||
} else {
|
||||
let args = relate_args_invariantly(relation, a.args, b.args)?;
|
||||
@ -360,7 +360,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
|
||||
Err(TypeError::Traits({
|
||||
let a = a.def_id;
|
||||
let b = b.def_id;
|
||||
ExpectedFound::new(true, a, b)
|
||||
ExpectedFound::new(a, b)
|
||||
}))
|
||||
} else {
|
||||
let args = relate_args_invariantly(relation, a.args, b.args)?;
|
||||
@ -508,9 +508,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
|
||||
let sz_b = sz_b.try_to_target_usize(cx);
|
||||
|
||||
match (sz_a, sz_b) {
|
||||
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
|
||||
TypeError::FixedArraySize(ExpectedFound::new(true, sz_a_val, sz_b_val)),
|
||||
),
|
||||
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
|
||||
Err(TypeError::FixedArraySize(ExpectedFound::new(sz_a_val, sz_b_val)))
|
||||
}
|
||||
_ => Err(err),
|
||||
}
|
||||
}
|
||||
@ -529,9 +529,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
|
||||
iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)),
|
||||
)?)
|
||||
} else if !(as_.is_empty() || bs.is_empty()) {
|
||||
Err(TypeError::TupleSize(ExpectedFound::new(true, as_.len(), bs.len())))
|
||||
Err(TypeError::TupleSize(ExpectedFound::new(as_.len(), bs.len())))
|
||||
} else {
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
Err(TypeError::Sorts(ExpectedFound::new(a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,7 +558,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
|
||||
Ok(Ty::new_pat(cx, ty, pat))
|
||||
}
|
||||
|
||||
_ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))),
|
||||
_ => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -637,7 +637,7 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))) }
|
||||
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))) }
|
||||
}
|
||||
|
||||
impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
|
||||
@ -658,9 +658,7 @@ impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
|
||||
) -> RelateResult<I, ty::TraitPredicate<I>> {
|
||||
let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
|
||||
if a.polarity != b.polarity {
|
||||
return Err(TypeError::PolarityMismatch(ExpectedFound::new(
|
||||
true, a.polarity, b.polarity,
|
||||
)));
|
||||
return Err(TypeError::PolarityMismatch(ExpectedFound::new(a.polarity, b.polarity)));
|
||||
}
|
||||
Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
|
||||
}
|
||||
|
@ -123,9 +123,7 @@ where
|
||||
}
|
||||
|
||||
// All other cases of inference are errors
|
||||
(ty::Infer(_), _) | (_, ty::Infer(_)) => {
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
}
|
||||
(ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
|
||||
|
||||
(ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
|
||||
assert!(!infcx.next_trait_solver());
|
||||
|
@ -579,7 +579,8 @@ impl<T, const N: usize> [T; N] {
|
||||
/// Returns a mutable slice containing the entire array. Equivalent to
|
||||
/// `&mut s[..]`.
|
||||
#[stable(feature = "array_as_slice", since = "1.57.0")]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
#[rustc_const_unstable(feature = "const_array_as_mut_slice", issue = "133333")]
|
||||
pub const fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -653,19 +653,28 @@ pub fn home_dir() -> Option<PathBuf> {
|
||||
/// may result in "insecure temporary file" security vulnerabilities. Consider
|
||||
/// using a crate that securely creates temporary files or directories.
|
||||
///
|
||||
/// Note that the returned value may be a symbolic link, not a directory.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
|
||||
/// set, otherwise for non-Android it returns `/tmp`. On Android, since there
|
||||
/// is no global temporary folder (it is usually allocated per-app), it returns
|
||||
/// `/data/local/tmp`.
|
||||
/// set, otherwise the value is OS-specific:
|
||||
/// - On Android, there is no global temporary folder (it is usually allocated
|
||||
/// per-app), it returns `/data/local/tmp`.
|
||||
/// - On Darwin-based OSes (macOS, iOS, etc) it returns the directory provided
|
||||
/// by `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)`, as recommended by [Apple's
|
||||
/// security guidelines][appledoc].
|
||||
/// - On all other unix-based OSes, it returns `/tmp`.
|
||||
///
|
||||
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
|
||||
/// [`GetTempPath`][GetTempPath], which this function uses internally.
|
||||
///
|
||||
/// Note that, this [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
|
||||
/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
|
||||
/// [appledoc]: https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::env;
|
||||
|
@ -698,12 +698,82 @@ pub fn page_size() -> usize {
|
||||
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||
}
|
||||
|
||||
// Returns the value for [`confstr(key, ...)`][posix_confstr]. Currently only
|
||||
// used on Darwin, but should work on any unix (in case we need to get
|
||||
// `_CS_PATH` or `_CS_V[67]_ENV` in the future).
|
||||
//
|
||||
// [posix_confstr]:
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html
|
||||
//
|
||||
// FIXME: Support `confstr` in Miri.
|
||||
#[cfg(all(target_vendor = "apple", not(miri)))]
|
||||
fn confstr(key: c_int, size_hint: Option<usize>) -> io::Result<OsString> {
|
||||
let mut buf: Vec<u8> = Vec::with_capacity(0);
|
||||
let mut bytes_needed_including_nul = size_hint
|
||||
.unwrap_or_else(|| {
|
||||
// Treat "None" as "do an extra call to get the length". In theory
|
||||
// we could move this into the loop below, but it's hard to do given
|
||||
// that it isn't 100% clear if it's legal to pass 0 for `len` when
|
||||
// the buffer isn't null.
|
||||
unsafe { libc::confstr(key, core::ptr::null_mut(), 0) }
|
||||
})
|
||||
.max(1);
|
||||
// If the value returned by `confstr` is greater than the len passed into
|
||||
// it, then the value was truncated, meaning we need to retry. Note that
|
||||
// while `confstr` results don't seem to change for a process, it's unclear
|
||||
// if this is guaranteed anywhere, so looping does seem required.
|
||||
while bytes_needed_including_nul > buf.capacity() {
|
||||
// We write into the spare capacity of `buf`. This lets us avoid
|
||||
// changing buf's `len`, which both simplifies `reserve` computation,
|
||||
// allows working with `Vec<u8>` instead of `Vec<MaybeUninit<u8>>`, and
|
||||
// may avoid a copy, since the Vec knows that none of the bytes are needed
|
||||
// when reallocating (well, in theory anyway).
|
||||
buf.reserve(bytes_needed_including_nul);
|
||||
// `confstr` returns
|
||||
// - 0 in the case of errors: we break and return an error.
|
||||
// - The number of bytes written, iff the provided buffer is enough to
|
||||
// hold the entire value: we break and return the data in `buf`.
|
||||
// - Otherwise, the number of bytes needed (including nul): we go
|
||||
// through the loop again.
|
||||
bytes_needed_including_nul =
|
||||
unsafe { libc::confstr(key, buf.as_mut_ptr().cast::<c_char>(), buf.capacity()) };
|
||||
}
|
||||
// `confstr` returns 0 in the case of an error.
|
||||
if bytes_needed_including_nul == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
// Safety: `confstr(..., buf.as_mut_ptr(), buf.capacity())` returned a
|
||||
// non-zero value, meaning `bytes_needed_including_nul` bytes were
|
||||
// initialized.
|
||||
unsafe {
|
||||
buf.set_len(bytes_needed_including_nul);
|
||||
// Remove the NUL-terminator.
|
||||
let last_byte = buf.pop();
|
||||
// ... and smoke-check that it *was* a NUL-terminator.
|
||||
assert_eq!(last_byte, Some(0), "`confstr` provided a string which wasn't nul-terminated");
|
||||
};
|
||||
Ok(OsString::from_vec(buf))
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor = "apple", not(miri)))]
|
||||
fn darwin_temp_dir() -> PathBuf {
|
||||
confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| {
|
||||
// It failed for whatever reason (there are several possible reasons),
|
||||
// so return the global one.
|
||||
PathBuf::from("/tmp")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
|
||||
if cfg!(target_os = "android") {
|
||||
PathBuf::from("/data/local/tmp")
|
||||
} else {
|
||||
PathBuf::from("/tmp")
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_vendor = "apple", not(miri)))] {
|
||||
darwin_temp_dir()
|
||||
} else if #[cfg(target_os = "android")] {
|
||||
PathBuf::from("/data/local/tmp")
|
||||
} else {
|
||||
PathBuf::from("/tmp")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -21,3 +21,28 @@ fn test_parse_glibc_version() {
|
||||
assert_eq!(parsed, super::parse_glibc_version(version_str));
|
||||
}
|
||||
}
|
||||
|
||||
// Smoke check `confstr`, do it for several hint values, to ensure our resizing
|
||||
// logic is correct.
|
||||
#[test]
|
||||
#[cfg(all(target_vendor = "apple", not(miri)))]
|
||||
fn test_confstr() {
|
||||
for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] {
|
||||
let value_nohint = super::confstr(key, None).unwrap_or_else(|e| {
|
||||
panic!("confstr({key}, None) failed: {e:?}");
|
||||
});
|
||||
let end = (value_nohint.len() + 1) * 2;
|
||||
for hint in 0..end {
|
||||
assert_eq!(
|
||||
super::confstr(key, Some(hint)).as_deref().ok(),
|
||||
Some(&*value_nohint),
|
||||
"confstr({key}, Some({hint})) failed",
|
||||
);
|
||||
}
|
||||
}
|
||||
// Smoke check that we don't loop forever or something if the input was not valid.
|
||||
for hint in [None, Some(0), Some(1)] {
|
||||
let hopefully_invalid = 123456789_i32;
|
||||
assert!(super::confstr(hopefully_invalid, hint).is_err());
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,16 @@
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address
|
||||
// CHECK-NOT: @__asan_global_UNSANITIZED
|
||||
#[no_mangle]
|
||||
#[no_sanitize(address)]
|
||||
pub static UNSANITIZED: u32 = 0;
|
||||
|
||||
// CHECK: @__asan_global_SANITIZED
|
||||
#[no_mangle]
|
||||
pub static SANITIZED: u32 = 0;
|
||||
|
||||
// CHECK-LABEL: ; no_sanitize::unsanitized
|
||||
// CHECK-NEXT: ; Function Attrs:
|
||||
// CHECK-NOT: sanitize_address
|
||||
|
@ -4,31 +4,37 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
fn invalid() {
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
{
|
||||
1
|
||||
};
|
||||
}
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
type InvalidTy = ();
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
mod invalid_module {}
|
||||
|
||||
fn main() {
|
||||
let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
(|| 1);
|
||||
}
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
struct F;
|
||||
|
||||
#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
|
||||
#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
impl F {
|
||||
#[no_sanitize(memory)]
|
||||
fn valid(&self) {}
|
||||
}
|
||||
|
||||
#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function
|
||||
static INVALID : i32 = 0;
|
||||
|
||||
#[no_sanitize(memory)]
|
||||
fn valid() {}
|
||||
|
||||
#[no_sanitize(address)]
|
||||
static VALID : i32 = 0;
|
||||
|
@ -1,55 +1,63 @@
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:7:5
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:7:19
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | / {
|
||||
LL | | 1
|
||||
LL | | };
|
||||
| |_____- not a function definition
|
||||
| |_____- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:13:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:13:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | type InvalidTy = ();
|
||||
| -------------------- not a function definition
|
||||
| -------------------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:16:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:16:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | mod invalid_module {}
|
||||
| --------------------- not a function definition
|
||||
| --------------------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:20:13
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:20:27
|
||||
|
|
||||
LL | let _ = #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | (|| 1);
|
||||
| ------ not a function definition
|
||||
| ------ not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:24:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:24:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | struct F;
|
||||
| --------- not a function definition
|
||||
| --------- not a function
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/no-sanitize.rs:27:1
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:27:15
|
||||
|
|
||||
LL | #[no_sanitize(memory)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
LL | / impl F {
|
||||
LL | | #[no_sanitize(memory)]
|
||||
LL | | fn valid(&self) {}
|
||||
LL | | }
|
||||
| |_- not a function definition
|
||||
| |_- not a function
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: `#[no_sanitize(memory)]` should be applied to a function
|
||||
--> $DIR/no-sanitize.rs:33:24
|
||||
|
|
||||
LL | #[no_sanitize(address, memory)]
|
||||
| ^^^^^^
|
||||
LL | static INVALID : i32 = 0;
|
||||
| ------------------------- not a function
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope
|
||||
LL | something_later!();
|
||||
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
||||
|
|
||||
note: a macro with the same name exists, but it appears later at here
|
||||
note: a macro with the same name exists, but it appears later
|
||||
--> $DIR/defined-later-issue-121061-2.rs:6:18
|
||||
|
|
||||
LL | macro_rules! something_later {
|
||||
|
@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope
|
||||
LL | something_later!();
|
||||
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
||||
|
|
||||
note: a macro with the same name exists, but it appears later at here
|
||||
note: a macro with the same name exists, but it appears later
|
||||
--> $DIR/defined-later-issue-121061.rs:5:14
|
||||
|
|
||||
LL | macro_rules! something_later {
|
||||
|
@ -0,0 +1,9 @@
|
||||
#![crate_type = "lib"]
|
||||
|
||||
macro_rules! sample { () => {} }
|
||||
|
||||
#[sample] //~ ERROR cannot find attribute `sample` in this scope
|
||||
#[derive(sample)] //~ ERROR cannot find derive macro `sample` in this scope
|
||||
//~| ERROR cannot find derive macro `sample` in this scope
|
||||
//~| ERROR cannot find derive macro `sample` in this scope
|
||||
pub struct S {}
|
@ -0,0 +1,42 @@
|
||||
error: cannot find derive macro `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
||||
|
|
||||
LL | macro_rules! sample { () => {} }
|
||||
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
|
||||
...
|
||||
LL | #[derive(sample)]
|
||||
| ^^^^^^
|
||||
|
||||
error: cannot find attribute `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3
|
||||
|
|
||||
LL | macro_rules! sample { () => {} }
|
||||
| ------ `sample` exists, but a declarative macro cannot be used as an attribute macro
|
||||
LL |
|
||||
LL | #[sample]
|
||||
| ^^^^^^
|
||||
|
||||
error: cannot find derive macro `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
||||
|
|
||||
LL | macro_rules! sample { () => {} }
|
||||
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
|
||||
...
|
||||
LL | #[derive(sample)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: cannot find derive macro `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
||||
|
|
||||
LL | macro_rules! sample { () => {} }
|
||||
| ------ `sample` exists, but a declarative macro cannot be used as a derive macro
|
||||
...
|
||||
LL | #[derive(sample)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
21
tests/ui/pattern/self-ctor-133272.rs
Normal file
21
tests/ui/pattern/self-ctor-133272.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/133272>, where a `ref Self` ctor
|
||||
//! makes it possible to hit a `delayed_bug` that was converted into a `span_bug` in
|
||||
//! <https://github.com/rust-lang/rust/pull/121208>, and hitting this reveals that we did not have
|
||||
//! test coverage for this specific code pattern (heh) previously.
|
||||
//!
|
||||
//! # References
|
||||
//!
|
||||
//! - ICE bug report: <https://github.com/rust-lang/rust/issues/133272>.
|
||||
//! - Previous PR to change `delayed_bug` -> `span_bug`:
|
||||
//! <https://github.com/rust-lang/rust/pull/121208>
|
||||
#![crate_type = "lib"]
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn fun() {
|
||||
let S { ref Self } = todo!();
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
//~| ERROR cannot find struct, variant or union type `S` in this scope
|
||||
}
|
||||
}
|
15
tests/ui/pattern/self-ctor-133272.stderr
Normal file
15
tests/ui/pattern/self-ctor-133272.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: expected identifier, found keyword `Self`
|
||||
--> $DIR/self-ctor-133272.rs:17:21
|
||||
|
|
||||
LL | let S { ref Self } = todo!();
|
||||
| ^^^^ expected identifier, found keyword
|
||||
|
||||
error[E0422]: cannot find struct, variant or union type `S` in this scope
|
||||
--> $DIR/self-ctor-133272.rs:17:13
|
||||
|
|
||||
LL | let S { ref Self } = todo!();
|
||||
| ^ not found in this scope
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0422`.
|
Loading…
Reference in New Issue
Block a user