Auto merge of #3363 - RalfJung:rustup, r=RalfJung
Rustup This should finally work again :)
This commit is contained in:
commit
305d2b0f5c
1528 changed files with 18007 additions and 11378 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
|
@ -235,6 +235,9 @@ jobs:
|
|||
- name: dist-loongarch64-linux
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-ohos
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
- name: dist-powerpc-linux
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
|
|
|
|||
377
Cargo.lock
377
Cargo.lock
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,7 @@ members = [
|
|||
"src/tools/clippy",
|
||||
"src/tools/clippy/clippy_dev",
|
||||
"src/tools/compiletest",
|
||||
"src/tools/run-make-support",
|
||||
"src/tools/error_index_generator",
|
||||
"src/tools/linkchecker",
|
||||
"src/tools/lint-docs",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
use std::borrow::{Borrow, Cow};
|
||||
use std::cmp;
|
||||
use std::fmt::{self, Write};
|
||||
use std::iter;
|
||||
use std::ops::Bound;
|
||||
use std::ops::Deref;
|
||||
use std::{borrow::Borrow, cmp, iter, ops::Bound};
|
||||
|
||||
use rustc_index::Idx;
|
||||
use tracing::debug;
|
||||
|
|
@ -32,7 +35,7 @@ where
|
|||
pub trait LayoutCalculator {
|
||||
type TargetDataLayoutRef: Borrow<TargetDataLayout>;
|
||||
|
||||
fn delayed_bug(&self, txt: String);
|
||||
fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>);
|
||||
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
|
||||
|
||||
fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
|
||||
|
|
|
|||
|
|
@ -171,8 +171,10 @@ pub struct TargetDataLayout {
|
|||
pub i32_align: AbiAndPrefAlign,
|
||||
pub i64_align: AbiAndPrefAlign,
|
||||
pub i128_align: AbiAndPrefAlign,
|
||||
pub f16_align: AbiAndPrefAlign,
|
||||
pub f32_align: AbiAndPrefAlign,
|
||||
pub f64_align: AbiAndPrefAlign,
|
||||
pub f128_align: AbiAndPrefAlign,
|
||||
pub pointer_size: Size,
|
||||
pub pointer_align: AbiAndPrefAlign,
|
||||
pub aggregate_align: AbiAndPrefAlign,
|
||||
|
|
@ -200,8 +202,10 @@ impl Default for TargetDataLayout {
|
|||
i32_align: AbiAndPrefAlign::new(align(32)),
|
||||
i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
|
||||
i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
|
||||
f16_align: AbiAndPrefAlign::new(align(16)),
|
||||
f32_align: AbiAndPrefAlign::new(align(32)),
|
||||
f64_align: AbiAndPrefAlign::new(align(64)),
|
||||
f128_align: AbiAndPrefAlign::new(align(128)),
|
||||
pointer_size: Size::from_bits(64),
|
||||
pointer_align: AbiAndPrefAlign::new(align(64)),
|
||||
aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
|
||||
|
|
@ -281,8 +285,10 @@ impl TargetDataLayout {
|
|||
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
|
||||
}
|
||||
["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
|
||||
["f16", ref a @ ..] => dl.f16_align = parse_align(a, "f16")?,
|
||||
["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?,
|
||||
["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?,
|
||||
["f128", ref a @ ..] => dl.f128_align = parse_align(a, "f128")?,
|
||||
// FIXME(erikdesjardins): we should be parsing nonzero address spaces
|
||||
// this will require replacing TargetDataLayout::{pointer_size,pointer_align}
|
||||
// with e.g. `fn pointer_size_in(AddressSpace)`
|
||||
|
|
@ -919,8 +925,10 @@ pub enum Primitive {
|
|||
/// a negative integer passed by zero-extension will appear positive in
|
||||
/// the callee, and most operations on it will produce the wrong values.
|
||||
Int(Integer, bool),
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F128,
|
||||
Pointer(AddressSpace),
|
||||
}
|
||||
|
||||
|
|
@ -931,8 +939,10 @@ impl Primitive {
|
|||
|
||||
match self {
|
||||
Int(i, _) => i.size(),
|
||||
F16 => Size::from_bits(16),
|
||||
F32 => Size::from_bits(32),
|
||||
F64 => Size::from_bits(64),
|
||||
F128 => Size::from_bits(128),
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different sizes
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
|
|
@ -946,8 +956,10 @@ impl Primitive {
|
|||
|
||||
match self {
|
||||
Int(i, _) => i.align(dl),
|
||||
F16 => dl.f16_align,
|
||||
F32 => dl.f32_align,
|
||||
F64 => dl.f64_align,
|
||||
F128 => dl.f128_align,
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different alignments
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
|
|
@ -1600,8 +1612,9 @@ pub enum PointerKind {
|
|||
SharedRef { frozen: bool },
|
||||
/// Mutable reference. `unpin` indicates the absence of any pinned data.
|
||||
MutableRef { unpin: bool },
|
||||
/// Box. `unpin` indicates the absence of any pinned data.
|
||||
Box { unpin: bool },
|
||||
/// Box. `unpin` indicates the absence of any pinned data. `global` indicates whether this box
|
||||
/// uses the global allocator or a custom one.
|
||||
Box { unpin: bool, global: bool },
|
||||
}
|
||||
|
||||
/// Note that this information is advisory only, and backends are free to ignore it.
|
||||
|
|
@ -1610,6 +1623,8 @@ pub enum PointerKind {
|
|||
pub struct PointeeInfo {
|
||||
pub size: Size,
|
||||
pub align: Align,
|
||||
/// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to
|
||||
/// be reliable.
|
||||
pub safe: Option<PointerKind>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -403,9 +403,10 @@ impl Default for Generics {
|
|||
/// A where-clause in a definition.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct WhereClause {
|
||||
/// `true` if we ate a `where` token: this can happen
|
||||
/// if we parsed no predicates (e.g. `struct Foo where {}`).
|
||||
/// This allows us to pretty-print accurately.
|
||||
/// `true` if we ate a `where` token.
|
||||
///
|
||||
/// This can happen if we parsed no predicates, e.g., `struct Foo where {}`.
|
||||
/// This allows us to pretty-print accurately and provide correct suggestion diagnostics.
|
||||
pub has_where_token: bool,
|
||||
pub predicates: ThinVec<WherePredicate>,
|
||||
pub span: Span,
|
||||
|
|
@ -670,6 +671,16 @@ impl Pat {
|
|||
});
|
||||
contains_never_pattern
|
||||
}
|
||||
|
||||
/// Return a name suitable for diagnostics.
|
||||
pub fn descr(&self) -> Option<String> {
|
||||
match &self.kind {
|
||||
PatKind::Wild => Some("_".to_string()),
|
||||
PatKind::Ident(BindingAnnotation::NONE, ident, None) => Some(format!("{ident}")),
|
||||
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single field in a struct pattern.
|
||||
|
|
@ -1052,6 +1063,7 @@ pub struct Local {
|
|||
pub ty: Option<P<Ty>>,
|
||||
pub kind: LocalKind,
|
||||
pub span: Span,
|
||||
pub colon_sp: Option<Span>,
|
||||
pub attrs: AttrVec,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
|
@ -1908,22 +1920,28 @@ pub struct FnSig {
|
|||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum FloatTy {
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F128,
|
||||
}
|
||||
|
||||
impl FloatTy {
|
||||
pub fn name_str(self) -> &'static str {
|
||||
match self {
|
||||
FloatTy::F16 => "f16",
|
||||
FloatTy::F32 => "f32",
|
||||
FloatTy::F64 => "f64",
|
||||
FloatTy::F128 => "f128",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(self) -> Symbol {
|
||||
match self {
|
||||
FloatTy::F16 => sym::f16,
|
||||
FloatTy::F32 => sym::f32,
|
||||
FloatTy::F64 => sym::f64,
|
||||
FloatTy::F128 => sym::f128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3007,18 +3025,29 @@ pub struct Trait {
|
|||
///
|
||||
/// If there is no where clause, then this is `false` with `DUMMY_SP`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
|
||||
pub struct TyAliasWhereClause(pub bool, pub Span);
|
||||
pub struct TyAliasWhereClause {
|
||||
pub has_where_token: bool,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// The span information for the two where clauses on a `TyAlias`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
|
||||
pub struct TyAliasWhereClauses {
|
||||
/// Before the equals sign.
|
||||
pub before: TyAliasWhereClause,
|
||||
/// After the equals sign.
|
||||
pub after: TyAliasWhereClause,
|
||||
/// The index in `TyAlias.generics.where_clause.predicates` that would split
|
||||
/// into predicates from the where clause before the equals sign and the ones
|
||||
/// from the where clause after the equals sign.
|
||||
pub split: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct TyAlias {
|
||||
pub defaultness: Defaultness,
|
||||
pub generics: Generics,
|
||||
/// The span information for the two where clauses (before equals, after equals)
|
||||
pub where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
|
||||
/// The index in `generics.where_clause.predicates` that would split into
|
||||
/// predicates from the where clause before the equals and the predicates
|
||||
/// from the where clause after the equals
|
||||
pub where_predicates_split: usize,
|
||||
pub where_clauses: TyAliasWhereClauses,
|
||||
pub bounds: GenericBounds,
|
||||
pub ty: Option<P<Ty>>,
|
||||
}
|
||||
|
|
@ -3325,7 +3354,7 @@ mod size_asserts {
|
|||
static_assert_size!(Item, 136);
|
||||
static_assert_size!(ItemKind, 64);
|
||||
static_assert_size!(LitKind, 24);
|
||||
static_assert_size!(Local, 72);
|
||||
static_assert_size!(Local, 80);
|
||||
static_assert_size!(MetaItemLit, 40);
|
||||
static_assert_size!(Param, 40);
|
||||
static_assert_size!(Pat, 72);
|
||||
|
|
|
|||
|
|
@ -609,7 +609,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
|
|||
}
|
||||
|
||||
pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||
let Local { id, pat, ty, kind, span, attrs, tokens } = local.deref_mut();
|
||||
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
|
||||
vis.visit_id(id);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
|
|
@ -624,6 +624,7 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
|||
}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
visit_opt(colon_sp, |sp| vis.visit_span(sp));
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
}
|
||||
|
|
@ -1079,8 +1080,8 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||
}) => {
|
||||
visit_defaultness(defaultness, vis);
|
||||
vis.visit_generics(generics);
|
||||
vis.visit_span(&mut where_clauses.0.1);
|
||||
vis.visit_span(&mut where_clauses.1.1);
|
||||
vis.visit_span(&mut where_clauses.before.span);
|
||||
vis.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, vis);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
}
|
||||
|
|
@ -1163,8 +1164,8 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
|
|||
}) => {
|
||||
visit_defaultness(defaultness, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
visitor.visit_span(&mut where_clauses.0.1);
|
||||
visitor.visit_span(&mut where_clauses.1.1);
|
||||
visitor.visit_span(&mut where_clauses.before.span);
|
||||
visitor.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
}
|
||||
|
|
@ -1257,8 +1258,8 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
|
|||
}) => {
|
||||
visit_defaultness(defaultness, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
visitor.visit_span(&mut where_clauses.0.1);
|
||||
visitor.visit_span(&mut where_clauses.1.1);
|
||||
visitor.visit_span(&mut where_clauses.before.span);
|
||||
visitor.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
}
|
||||
|
|
@ -1603,7 +1604,10 @@ pub fn noop_visit_capture_by<T: MutVisitor>(capture_by: &mut CaptureBy, vis: &mu
|
|||
}
|
||||
}
|
||||
|
||||
/// Some value for the AST node that is valid but possibly meaningless.
|
||||
/// Some value for the AST node that is valid but possibly meaningless. Similar
|
||||
/// to `Default` but not intended for wide use. The value will never be used
|
||||
/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
|
||||
/// case where its closure panics.
|
||||
pub trait DummyAstNode {
|
||||
fn dummy() -> Self;
|
||||
}
|
||||
|
|
@ -1678,19 +1682,6 @@ impl DummyAstNode for Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Block {
|
||||
fn dummy() -> Self {
|
||||
Block {
|
||||
stmts: Default::default(),
|
||||
id: DUMMY_NODE_ID,
|
||||
rules: BlockCheckMode::Default,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
could_be_bare_literal: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Crate {
|
||||
fn dummy() -> Self {
|
||||
Crate {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::token::CommentKind;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
|
||||
use rustc_span::{BytePos, Symbol};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
@ -131,126 +130,3 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
|||
}
|
||||
data
|
||||
}
|
||||
|
||||
/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
|
||||
/// Otherwise returns `Some(k)` where `k` is first char offset after that leading
|
||||
/// whitespace. Note that `k` may be outside bounds of `s`.
|
||||
fn all_whitespace(s: &str, col: CharPos) -> Option<usize> {
|
||||
let mut idx = 0;
|
||||
for (i, ch) in s.char_indices().take(col.to_usize()) {
|
||||
if !ch.is_whitespace() {
|
||||
return None;
|
||||
}
|
||||
idx = i + ch.len_utf8();
|
||||
}
|
||||
Some(idx)
|
||||
}
|
||||
|
||||
fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str {
|
||||
let len = s.len();
|
||||
match all_whitespace(s, col) {
|
||||
Some(col) => {
|
||||
if col < len {
|
||||
&s[col..]
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
None => s,
|
||||
}
|
||||
}
|
||||
|
||||
fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec<String> {
|
||||
let mut res: Vec<String> = vec![];
|
||||
let mut lines = text.lines();
|
||||
// just push the first line
|
||||
res.extend(lines.next().map(|it| it.to_string()));
|
||||
// for other lines, strip common whitespace prefix
|
||||
for line in lines {
|
||||
res.push(trim_whitespace_prefix(line, col).to_string())
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
// it appears this function is called only from pprust... that's
|
||||
// probably not a good thing.
|
||||
pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment> {
|
||||
let sm = SourceMap::new(sm.path_mapping().clone());
|
||||
let source_file = sm.new_source_file(path, src);
|
||||
let text = (*source_file.src.as_ref().unwrap()).clone();
|
||||
|
||||
let text: &str = text.as_str();
|
||||
let start_bpos = source_file.start_pos;
|
||||
let mut pos = 0;
|
||||
let mut comments: Vec<Comment> = Vec::new();
|
||||
let mut code_to_the_left = false;
|
||||
|
||||
if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
|
||||
comments.push(Comment {
|
||||
style: CommentStyle::Isolated,
|
||||
lines: vec![text[..shebang_len].to_string()],
|
||||
pos: start_bpos,
|
||||
});
|
||||
pos += shebang_len;
|
||||
}
|
||||
|
||||
for token in rustc_lexer::tokenize(&text[pos..]) {
|
||||
let token_text = &text[pos..pos + token.len as usize];
|
||||
match token.kind {
|
||||
rustc_lexer::TokenKind::Whitespace => {
|
||||
if let Some(mut idx) = token_text.find('\n') {
|
||||
code_to_the_left = false;
|
||||
while let Some(next_newline) = &token_text[idx + 1..].find('\n') {
|
||||
idx += 1 + next_newline;
|
||||
comments.push(Comment {
|
||||
style: CommentStyle::BlankLine,
|
||||
lines: vec![],
|
||||
pos: start_bpos + BytePos((pos + idx) as u32),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
rustc_lexer::TokenKind::BlockComment { doc_style, .. } => {
|
||||
if doc_style.is_none() {
|
||||
let code_to_the_right = !matches!(
|
||||
text[pos + token.len as usize..].chars().next(),
|
||||
Some('\r' | '\n')
|
||||
);
|
||||
let style = match (code_to_the_left, code_to_the_right) {
|
||||
(_, true) => CommentStyle::Mixed,
|
||||
(false, false) => CommentStyle::Isolated,
|
||||
(true, false) => CommentStyle::Trailing,
|
||||
};
|
||||
|
||||
// Count the number of chars since the start of the line by rescanning.
|
||||
let pos_in_file = start_bpos + BytePos(pos as u32);
|
||||
let line_begin_in_file = source_file.line_begin_pos(pos_in_file);
|
||||
let line_begin_pos = (line_begin_in_file - start_bpos).to_usize();
|
||||
let col = CharPos(text[line_begin_pos..pos].chars().count());
|
||||
|
||||
let lines = split_block_comment_into_lines(token_text, col);
|
||||
comments.push(Comment { style, lines, pos: pos_in_file })
|
||||
}
|
||||
}
|
||||
rustc_lexer::TokenKind::LineComment { doc_style } => {
|
||||
if doc_style.is_none() {
|
||||
comments.push(Comment {
|
||||
style: if code_to_the_left {
|
||||
CommentStyle::Trailing
|
||||
} else {
|
||||
CommentStyle::Isolated
|
||||
},
|
||||
lines: vec![token_text.to_string()],
|
||||
pos: start_bpos + BytePos(pos as u32),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
code_to_the_left = true;
|
||||
}
|
||||
}
|
||||
pos += token.len as usize;
|
||||
}
|
||||
|
||||
comments
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@
|
|||
|
||||
use crate::ast::*;
|
||||
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub use rustc_ast_ir::visit::VisitorResult;
|
||||
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum AssocCtxt {
|
||||
Trait,
|
||||
|
|
@ -101,51 +102,6 @@ pub enum LifetimeCtxt {
|
|||
GenericArg,
|
||||
}
|
||||
|
||||
/// Similar to the `Try` trait, but also implemented for `()`.
|
||||
pub trait VisitorResult {
|
||||
type Residual;
|
||||
fn output() -> Self;
|
||||
fn from_residual(residual: Self::Residual) -> Self;
|
||||
fn branch(self) -> ControlFlow<Self::Residual>;
|
||||
}
|
||||
|
||||
impl VisitorResult for () {
|
||||
type Residual = !;
|
||||
|
||||
fn output() -> Self {}
|
||||
fn from_residual(_: !) -> Self {}
|
||||
fn branch(self) -> ControlFlow<!> {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> VisitorResult for ControlFlow<T> {
|
||||
type Residual = T;
|
||||
|
||||
fn output() -> Self {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
fn from_residual(residual: Self::Residual) -> Self {
|
||||
ControlFlow::Break(residual)
|
||||
}
|
||||
fn branch(self) -> ControlFlow<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try_visit {
|
||||
($e:expr) => {
|
||||
match $crate::visit::VisitorResult::branch($e) {
|
||||
core::ops::ControlFlow::Continue(()) => (),
|
||||
#[allow(unreachable_code)]
|
||||
core::ops::ControlFlow::Break(r) => {
|
||||
return $crate::visit::VisitorResult::from_residual(r);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Each method of the `Visitor` trait is a hook to be potentially
|
||||
/// overridden. Each method's default implementation recursively visits
|
||||
/// the substructure of the input via the corresponding `walk` method;
|
||||
|
|
@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! walk_list {
|
||||
($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
|
||||
for elem in $list {
|
||||
$crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! visit_opt {
|
||||
($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
|
||||
if let Some(x) = $opt {
|
||||
$crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
|
||||
walk_list!(visitor, visit_item, &krate.items);
|
||||
walk_list!(visitor, visit_attribute, &krate.attrs);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#![cfg_attr(feature = "nightly", feature(never_type))]
|
||||
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
|
||||
|
|
@ -5,6 +6,8 @@
|
|||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
||||
pub mod visit;
|
||||
|
||||
/// The movability of a coroutine / closure literal:
|
||||
/// whether a coroutine contains self-references, causing it to be `!Unpin`.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
||||
|
|
|
|||
82
compiler/rustc_ast_ir/src/visit.rs
Normal file
82
compiler/rustc_ast_ir/src/visit.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
use core::ops::ControlFlow;
|
||||
|
||||
/// Similar to the `Try` trait, but also implemented for `()`.
|
||||
pub trait VisitorResult {
|
||||
type Residual;
|
||||
fn output() -> Self;
|
||||
fn from_residual(residual: Self::Residual) -> Self;
|
||||
fn from_branch(b: ControlFlow<Self::Residual>) -> Self;
|
||||
fn branch(self) -> ControlFlow<Self::Residual>;
|
||||
}
|
||||
|
||||
impl VisitorResult for () {
|
||||
#[cfg(feature = "nightly")]
|
||||
type Residual = !;
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
type Residual = core::ops::Infallible;
|
||||
|
||||
fn output() -> Self {}
|
||||
fn from_residual(_: Self::Residual) -> Self {}
|
||||
fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
|
||||
fn branch(self) -> ControlFlow<Self::Residual> {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> VisitorResult for ControlFlow<T> {
|
||||
type Residual = T;
|
||||
|
||||
fn output() -> Self {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
fn from_residual(residual: Self::Residual) -> Self {
|
||||
ControlFlow::Break(residual)
|
||||
}
|
||||
fn from_branch(b: Self) -> Self {
|
||||
b
|
||||
}
|
||||
fn branch(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try_visit {
|
||||
($e:expr) => {
|
||||
match $crate::visit::VisitorResult::branch($e) {
|
||||
core::ops::ControlFlow::Continue(()) => (),
|
||||
#[allow(unreachable_code)]
|
||||
core::ops::ControlFlow::Break(r) => {
|
||||
return $crate::visit::VisitorResult::from_residual(r);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! visit_opt {
|
||||
($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
|
||||
if let Some(x) = $opt {
|
||||
$crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! walk_list {
|
||||
($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
|
||||
for elem in $list {
|
||||
$crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! walk_visitable_list {
|
||||
($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => {
|
||||
for elem in $list {
|
||||
$crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ use std::collections::hash_map::Entry;
|
|||
use std::fmt::Write;
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
pub(crate) fn lower_inline_asm(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagnosticMessageOp,
|
||||
codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
|
@ -41,7 +41,7 @@ pub struct InvalidAbi {
|
|||
pub struct InvalidAbiReason(pub &'static str);
|
||||
|
||||
impl AddToDiagnostic for InvalidAbiReason {
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
|
|
|
|||
|
|
@ -125,12 +125,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let lit_kind = match LitKind::from_token_lit(*token_lit) {
|
||||
Ok(lit_kind) => lit_kind,
|
||||
Err(err) => {
|
||||
let guar = report_lit_error(
|
||||
&self.tcx.sess.parse_sess,
|
||||
err,
|
||||
*token_lit,
|
||||
e.span,
|
||||
);
|
||||
let guar =
|
||||
report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span);
|
||||
LitKind::Err(guar)
|
||||
}
|
||||
};
|
||||
|
|
@ -721,7 +717,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
sym::track_caller,
|
||||
span,
|
||||
)))),
|
||||
id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
|
||||
id: self.tcx.sess.psess.attr_id_generator.mk_attr_id(),
|
||||
style: AttrStyle::Outer,
|
||||
span: unstable_span,
|
||||
}],
|
||||
|
|
@ -764,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Some(hir::CoroutineKind::Coroutine(_))
|
||||
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
|
||||
| None => {
|
||||
return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||
await_kw_span,
|
||||
item_span: self.current_item,
|
||||
}));
|
||||
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
|
||||
// is not accidentally orphaned.
|
||||
let stmt_id = self.next_id();
|
||||
let expr_err = self.expr(
|
||||
expr.span,
|
||||
hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||
await_kw_span,
|
||||
item_span: self.current_item,
|
||||
})),
|
||||
);
|
||||
return hir::ExprKind::Block(
|
||||
self.block_all(
|
||||
expr.span,
|
||||
arena_vec![self; hir::Stmt {
|
||||
hir_id: stmt_id,
|
||||
kind: hir::StmtKind::Semi(expr),
|
||||
span: expr.span,
|
||||
}],
|
||||
Some(self.arena.alloc(expr_err)),
|
||||
),
|
||||
None,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1499,13 +1513,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
|
||||
let yielded =
|
||||
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
|
||||
|
||||
let is_async_gen = match self.coroutine_kind {
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
|
||||
return hir::ExprKind::Err(
|
||||
self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
|
||||
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
|
||||
// is not accidentally orphaned.
|
||||
let stmt_id = self.next_id();
|
||||
let expr_err = self.expr(
|
||||
yielded.span,
|
||||
hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
|
||||
);
|
||||
return hir::ExprKind::Block(
|
||||
self.block_all(
|
||||
yielded.span,
|
||||
arena_vec![self; hir::Stmt {
|
||||
hir_id: stmt_id,
|
||||
kind: hir::StmtKind::Semi(yielded),
|
||||
span: yielded.span,
|
||||
}],
|
||||
Some(self.arena.alloc(expr_err)),
|
||||
),
|
||||
None,
|
||||
);
|
||||
}
|
||||
Some(hir::CoroutineKind::Coroutine(_)) => {
|
||||
|
|
@ -1535,9 +1569,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
};
|
||||
|
||||
let yielded =
|
||||
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
|
||||
|
||||
if is_async_gen {
|
||||
// `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
|
||||
// This ensures that we store our resumed `ResumeContext` correctly, and also that
|
||||
|
|
@ -1756,7 +1787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
// `#[allow(unreachable_code)]`
|
||||
let attr = attr::mk_attr_nested_word(
|
||||
&self.tcx.sess.parse_sess.attr_id_generator,
|
||||
&self.tcx.sess.psess.attr_id_generator,
|
||||
AttrStyle::Outer,
|
||||
sym::allow,
|
||||
sym::unreachable_code,
|
||||
|
|
|
|||
|
|
@ -33,19 +33,20 @@ pub(super) struct ItemLowerer<'a, 'hir> {
|
|||
/// clause if it exists.
|
||||
fn add_ty_alias_where_clause(
|
||||
generics: &mut ast::Generics,
|
||||
mut where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
|
||||
mut where_clauses: TyAliasWhereClauses,
|
||||
prefer_first: bool,
|
||||
) {
|
||||
if !prefer_first {
|
||||
where_clauses = (where_clauses.1, where_clauses.0);
|
||||
}
|
||||
if where_clauses.0.0 || !where_clauses.1.0 {
|
||||
generics.where_clause.has_where_token = where_clauses.0.0;
|
||||
generics.where_clause.span = where_clauses.0.1;
|
||||
} else {
|
||||
generics.where_clause.has_where_token = where_clauses.1.0;
|
||||
generics.where_clause.span = where_clauses.1.1;
|
||||
(where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
|
||||
}
|
||||
let where_clause =
|
||||
if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
|
||||
where_clauses.before
|
||||
} else {
|
||||
where_clauses.after
|
||||
};
|
||||
generics.where_clause.has_where_token = where_clause.has_where_token;
|
||||
generics.where_clause.span = where_clause.span;
|
||||
}
|
||||
|
||||
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
|
|
|
|||
|
|
@ -2272,6 +2272,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.expr_block(block)
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
|
||||
match c.value.kind {
|
||||
ExprKind::Underscore => {
|
||||
|
|
|
|||
|
|
@ -280,4 +280,5 @@ ast_passes_where_clause_after_type_alias = where clauses are not allowed after t
|
|||
|
||||
ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
|
||||
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
.suggestion = move it to the end of the type declaration
|
||||
.remove_suggestion = remove this `where`
|
||||
.move_suggestion = move it to the end of the type declaration
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::walk_list;
|
||||
use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust::{self, State};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
|
|
@ -18,7 +17,7 @@ use rustc_parse::validate_attr;
|
|||
use rustc_session::lint::builtin::{
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
};
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -138,38 +137,42 @@ impl<'a> AstValidator<'a> {
|
|||
&mut self,
|
||||
ty_alias: &TyAlias,
|
||||
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
|
||||
let before_predicates =
|
||||
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
|
||||
|
||||
if ty_alias.ty.is_none() || before_predicates.is_empty() {
|
||||
if ty_alias.ty.is_none() || !ty_alias.where_clauses.before.has_where_token {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut state = State::new();
|
||||
if !ty_alias.where_clauses.1.0 {
|
||||
state.space();
|
||||
state.word_space("where");
|
||||
} else {
|
||||
state.word_space(",");
|
||||
}
|
||||
let mut first = true;
|
||||
for p in before_predicates {
|
||||
if !first {
|
||||
state.word_space(",");
|
||||
}
|
||||
first = false;
|
||||
state.print_where_predicate(p);
|
||||
}
|
||||
let (before_predicates, after_predicates) =
|
||||
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split);
|
||||
let span = ty_alias.where_clauses.before.span;
|
||||
|
||||
let span = ty_alias.where_clauses.0.1;
|
||||
Err(errors::WhereClauseBeforeTypeAlias {
|
||||
span,
|
||||
sugg: errors::WhereClauseBeforeTypeAliasSugg {
|
||||
let sugg = if !before_predicates.is_empty() || !ty_alias.where_clauses.after.has_where_token
|
||||
{
|
||||
let mut state = State::new();
|
||||
|
||||
if !ty_alias.where_clauses.after.has_where_token {
|
||||
state.space();
|
||||
state.word_space("where");
|
||||
}
|
||||
|
||||
let mut first = after_predicates.is_empty();
|
||||
for p in before_predicates {
|
||||
if !first {
|
||||
state.word_space(",");
|
||||
}
|
||||
first = false;
|
||||
state.print_where_predicate(p);
|
||||
}
|
||||
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Move {
|
||||
left: span,
|
||||
snippet: state.s.eof(),
|
||||
right: ty_alias.where_clauses.1.1.shrink_to_hi(),
|
||||
},
|
||||
})
|
||||
right: ty_alias.where_clauses.after.span.shrink_to_hi(),
|
||||
}
|
||||
} else {
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Remove { span }
|
||||
};
|
||||
|
||||
Err(errors::WhereClauseBeforeTypeAlias { span, sugg })
|
||||
}
|
||||
|
||||
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
|
||||
|
|
@ -457,8 +460,7 @@ impl<'a> AstValidator<'a> {
|
|||
fn check_foreign_ty_genericless(
|
||||
&self,
|
||||
generics: &Generics,
|
||||
before_where_clause: &TyAliasWhereClause,
|
||||
after_where_clause: &TyAliasWhereClause,
|
||||
where_clauses: &TyAliasWhereClauses,
|
||||
) {
|
||||
let cannot_have = |span, descr, remove_descr| {
|
||||
self.dcx().emit_err(errors::ExternTypesCannotHave {
|
||||
|
|
@ -473,14 +475,14 @@ impl<'a> AstValidator<'a> {
|
|||
cannot_have(generics.span, "generic parameters", "generic parameters");
|
||||
}
|
||||
|
||||
let check_where_clause = |where_clause: &TyAliasWhereClause| {
|
||||
if let TyAliasWhereClause(true, where_clause_span) = where_clause {
|
||||
cannot_have(*where_clause_span, "`where` clauses", "`where` clause");
|
||||
let check_where_clause = |where_clause: TyAliasWhereClause| {
|
||||
if where_clause.has_where_token {
|
||||
cannot_have(where_clause.span, "`where` clauses", "`where` clause");
|
||||
}
|
||||
};
|
||||
|
||||
check_where_clause(before_where_clause);
|
||||
check_where_clause(after_where_clause);
|
||||
check_where_clause(where_clauses.before);
|
||||
check_where_clause(where_clauses.after);
|
||||
}
|
||||
|
||||
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
|
||||
|
|
@ -747,7 +749,7 @@ impl<'a> AstValidator<'a> {
|
|||
id,
|
||||
span,
|
||||
fluent::ast_passes_extern_without_abi,
|
||||
BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
|
||||
BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -832,7 +834,7 @@ fn validate_generic_param_order(
|
|||
|
||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_attribute(&mut self, attr: &Attribute) {
|
||||
validate_attr::check_attr(&self.session.parse_sess, attr);
|
||||
validate_attr::check_attr(&self.session.psess, attr);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
|
|
@ -1122,9 +1124,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
||||
self.dcx().emit_err(err);
|
||||
}
|
||||
} else if where_clauses.1.0 {
|
||||
} else if where_clauses.after.has_where_token {
|
||||
self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
|
||||
span: where_clauses.1.1,
|
||||
span: where_clauses.after.span,
|
||||
help: self.session.is_nightly_build().then_some(()),
|
||||
});
|
||||
}
|
||||
|
|
@ -1154,7 +1156,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_defaultness(fi.span, *defaultness);
|
||||
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
|
||||
self.check_type_no_bounds(bounds, "`extern` blocks");
|
||||
self.check_foreign_ty_genericless(generics, &where_clauses.0, &where_clauses.1);
|
||||
self.check_foreign_ty_genericless(generics, where_clauses);
|
||||
self.check_foreign_item_ascii_only(fi.ident);
|
||||
}
|
||||
ForeignItemKind::Static(_, _, body) => {
|
||||
|
|
@ -1405,7 +1407,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign,
|
||||
_ => fluent::ast_passes_pattern_in_bodiless,
|
||||
};
|
||||
let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
|
||||
let diag = BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident);
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
id,
|
||||
|
|
@ -1477,15 +1479,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
if let AssocItemKind::Type(ty_alias) = &item.kind
|
||||
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
|
||||
{
|
||||
let sugg = match err.sugg {
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Remove { .. } => None,
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Move { snippet, right, .. } => {
|
||||
Some((right, snippet))
|
||||
}
|
||||
};
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||
item.id,
|
||||
err.span,
|
||||
fluent::ast_passes_deprecated_where_clause_location,
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
||||
err.sugg.right,
|
||||
err.sugg.snippet,
|
||||
),
|
||||
BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use rustc_ast::ParamKindOrd;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagnosticMessageOp,
|
||||
codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
|
@ -374,7 +374,7 @@ pub struct EmptyLabelManySpans(pub Vec<Span>);
|
|||
|
||||
// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
|
||||
impl AddToDiagnostic for EmptyLabelManySpans {
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
|
|
@ -515,17 +515,25 @@ pub struct WhereClauseBeforeTypeAlias {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub struct WhereClauseBeforeTypeAliasSugg {
|
||||
#[suggestion_part(code = "")]
|
||||
pub left: Span,
|
||||
pub snippet: String,
|
||||
#[suggestion_part(code = "{snippet}")]
|
||||
pub right: Span,
|
||||
|
||||
pub enum WhereClauseBeforeTypeAliasSugg {
|
||||
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
|
||||
Remove {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[multipart_suggestion(
|
||||
ast_passes_move_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
Move {
|
||||
#[suggestion_part(code = "")]
|
||||
left: Span,
|
||||
snippet: String,
|
||||
#[suggestion_part(code = "{snippet}")]
|
||||
right: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -735,7 +743,7 @@ pub struct StableFeature {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for StableFeature {
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use crate::errors;
|
|||
macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
|
|
@ -34,6 +35,7 @@ macro_rules! gate {
|
|||
macro_rules! gate_alt {
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(&$visitor.sess, $name, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
|
|
@ -73,6 +75,7 @@ struct PostExpansionVisitor<'a> {
|
|||
}
|
||||
|
||||
impl<'a> PostExpansionVisitor<'a> {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||
let ast::StrLit { symbol_unescaped, span, .. } = abi;
|
||||
|
||||
|
|
@ -507,7 +510,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
check_incompatible_features(sess, features);
|
||||
let mut visitor = PostExpansionVisitor { sess, features };
|
||||
|
||||
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
||||
let spans = sess.psess.gated_spans.spans.borrow();
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
|
|
@ -579,6 +582,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
if let Ok(snippet) = sm.span_to_snippet(span)
|
||||
&& snippet == "!"
|
||||
{
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||
.emit();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
# tidy-alphabetical-start
|
||||
itertools = "0.11"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
thin-vec = "0.2.12"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc_ast::ptr::P;
|
|||
use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
||||
use rustc_ast::util::comments::{Comment, CommentStyle};
|
||||
use rustc_ast::util::parser;
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
||||
|
|
@ -24,7 +24,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
|||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{SourceMap, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
||||
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
|
||||
use rustc_span::{BytePos, CharPos, FileName, Pos, Span, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
@ -59,6 +59,127 @@ pub struct Comments<'a> {
|
|||
current: usize,
|
||||
}
|
||||
|
||||
/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
|
||||
/// Otherwise returns `Some(k)` where `k` is first char offset after that leading
|
||||
/// whitespace. Note that `k` may be outside bounds of `s`.
|
||||
fn all_whitespace(s: &str, col: CharPos) -> Option<usize> {
|
||||
let mut idx = 0;
|
||||
for (i, ch) in s.char_indices().take(col.to_usize()) {
|
||||
if !ch.is_whitespace() {
|
||||
return None;
|
||||
}
|
||||
idx = i + ch.len_utf8();
|
||||
}
|
||||
Some(idx)
|
||||
}
|
||||
|
||||
fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str {
|
||||
let len = s.len();
|
||||
match all_whitespace(s, col) {
|
||||
Some(col) => {
|
||||
if col < len {
|
||||
&s[col..]
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
None => s,
|
||||
}
|
||||
}
|
||||
|
||||
fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec<String> {
|
||||
let mut res: Vec<String> = vec![];
|
||||
let mut lines = text.lines();
|
||||
// just push the first line
|
||||
res.extend(lines.next().map(|it| it.to_string()));
|
||||
// for other lines, strip common whitespace prefix
|
||||
for line in lines {
|
||||
res.push(trim_whitespace_prefix(line, col).to_string())
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment> {
|
||||
let sm = SourceMap::new(sm.path_mapping().clone());
|
||||
let source_file = sm.new_source_file(path, src);
|
||||
let text = (*source_file.src.as_ref().unwrap()).clone();
|
||||
|
||||
let text: &str = text.as_str();
|
||||
let start_bpos = source_file.start_pos;
|
||||
let mut pos = 0;
|
||||
let mut comments: Vec<Comment> = Vec::new();
|
||||
let mut code_to_the_left = false;
|
||||
|
||||
if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
|
||||
comments.push(Comment {
|
||||
style: CommentStyle::Isolated,
|
||||
lines: vec![text[..shebang_len].to_string()],
|
||||
pos: start_bpos,
|
||||
});
|
||||
pos += shebang_len;
|
||||
}
|
||||
|
||||
for token in rustc_lexer::tokenize(&text[pos..]) {
|
||||
let token_text = &text[pos..pos + token.len as usize];
|
||||
match token.kind {
|
||||
rustc_lexer::TokenKind::Whitespace => {
|
||||
if let Some(mut idx) = token_text.find('\n') {
|
||||
code_to_the_left = false;
|
||||
while let Some(next_newline) = &token_text[idx + 1..].find('\n') {
|
||||
idx += 1 + next_newline;
|
||||
comments.push(Comment {
|
||||
style: CommentStyle::BlankLine,
|
||||
lines: vec![],
|
||||
pos: start_bpos + BytePos((pos + idx) as u32),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
rustc_lexer::TokenKind::BlockComment { doc_style, .. } => {
|
||||
if doc_style.is_none() {
|
||||
let code_to_the_right = !matches!(
|
||||
text[pos + token.len as usize..].chars().next(),
|
||||
Some('\r' | '\n')
|
||||
);
|
||||
let style = match (code_to_the_left, code_to_the_right) {
|
||||
(_, true) => CommentStyle::Mixed,
|
||||
(false, false) => CommentStyle::Isolated,
|
||||
(true, false) => CommentStyle::Trailing,
|
||||
};
|
||||
|
||||
// Count the number of chars since the start of the line by rescanning.
|
||||
let pos_in_file = start_bpos + BytePos(pos as u32);
|
||||
let line_begin_in_file = source_file.line_begin_pos(pos_in_file);
|
||||
let line_begin_pos = (line_begin_in_file - start_bpos).to_usize();
|
||||
let col = CharPos(text[line_begin_pos..pos].chars().count());
|
||||
|
||||
let lines = split_block_comment_into_lines(token_text, col);
|
||||
comments.push(Comment { style, lines, pos: pos_in_file })
|
||||
}
|
||||
}
|
||||
rustc_lexer::TokenKind::LineComment { doc_style } => {
|
||||
if doc_style.is_none() {
|
||||
comments.push(Comment {
|
||||
style: if code_to_the_left {
|
||||
CommentStyle::Trailing
|
||||
} else {
|
||||
CommentStyle::Isolated
|
||||
},
|
||||
lines: vec![token_text.to_string()],
|
||||
pos: start_bpos + BytePos(pos as u32),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
code_to_the_left = true;
|
||||
}
|
||||
}
|
||||
pos += token.len as usize;
|
||||
}
|
||||
|
||||
comments
|
||||
}
|
||||
|
||||
impl<'a> Comments<'a> {
|
||||
pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
|
||||
let comments = gather_comments(sm, filename, input);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ impl<'a> State<'a> {
|
|||
defaultness,
|
||||
generics,
|
||||
where_clauses,
|
||||
where_predicates_split,
|
||||
bounds,
|
||||
ty,
|
||||
}) => {
|
||||
|
|
@ -51,7 +50,6 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
*where_clauses,
|
||||
*where_predicates_split,
|
||||
bounds,
|
||||
ty.as_deref(),
|
||||
vis,
|
||||
|
|
@ -108,15 +106,14 @@ impl<'a> State<'a> {
|
|||
&mut self,
|
||||
ident: Ident,
|
||||
generics: &ast::Generics,
|
||||
where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
|
||||
where_predicates_split: usize,
|
||||
where_clauses: ast::TyAliasWhereClauses,
|
||||
bounds: &ast::GenericBounds,
|
||||
ty: Option<&ast::Ty>,
|
||||
vis: &ast::Visibility,
|
||||
defaultness: ast::Defaultness,
|
||||
) {
|
||||
let (before_predicates, after_predicates) =
|
||||
generics.where_clause.predicates.split_at(where_predicates_split);
|
||||
generics.where_clause.predicates.split_at(where_clauses.split);
|
||||
self.head("");
|
||||
self.print_visibility(vis);
|
||||
self.print_defaultness(defaultness);
|
||||
|
|
@ -127,13 +124,13 @@ impl<'a> State<'a> {
|
|||
self.word_nbsp(":");
|
||||
self.print_type_bounds(bounds);
|
||||
}
|
||||
self.print_where_clause_parts(where_clauses.0.0, before_predicates);
|
||||
self.print_where_clause_parts(where_clauses.before.has_where_token, before_predicates);
|
||||
if let Some(ty) = ty {
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
self.print_type(ty);
|
||||
}
|
||||
self.print_where_clause_parts(where_clauses.1.0, after_predicates);
|
||||
self.print_where_clause_parts(where_clauses.after.has_where_token, after_predicates);
|
||||
self.word(";");
|
||||
self.end(); // end inner head-block
|
||||
self.end(); // end outer head-block
|
||||
|
|
@ -249,7 +246,6 @@ impl<'a> State<'a> {
|
|||
defaultness,
|
||||
generics,
|
||||
where_clauses,
|
||||
where_predicates_split,
|
||||
bounds,
|
||||
ty,
|
||||
}) => {
|
||||
|
|
@ -257,7 +253,6 @@ impl<'a> State<'a> {
|
|||
item.ident,
|
||||
generics,
|
||||
*where_clauses,
|
||||
*where_predicates_split,
|
||||
bounds,
|
||||
ty.as_deref(),
|
||||
&item.vis,
|
||||
|
|
@ -536,7 +531,6 @@ impl<'a> State<'a> {
|
|||
defaultness,
|
||||
generics,
|
||||
where_clauses,
|
||||
where_predicates_split,
|
||||
bounds,
|
||||
ty,
|
||||
}) => {
|
||||
|
|
@ -544,7 +538,6 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
*where_clauses,
|
||||
*where_predicates_split,
|
||||
bounds,
|
||||
ty.as_deref(),
|
||||
vis,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,16 @@ attr_incorrect_meta_item =
|
|||
attr_incorrect_repr_format_align_one_arg =
|
||||
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
|
||||
|
||||
attr_incorrect_repr_format_expect_literal_integer =
|
||||
incorrect `repr(align)` attribute format: `align` expects a literal integer as argument
|
||||
|
||||
attr_incorrect_repr_format_generic =
|
||||
incorrect `repr({$repr_arg})` attribute format
|
||||
.suggestion = use parentheses instead
|
||||
|
||||
attr_incorrect_repr_format_packed_expect_integer =
|
||||
incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument
|
||||
|
||||
attr_incorrect_repr_format_packed_one_or_zero_arg =
|
||||
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
|
|||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::hygiene::Transparency;
|
||||
|
|
@ -516,6 +516,7 @@ pub struct Condition {
|
|||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
pub fn cfg_matches(
|
||||
cfg: &ast::MetaItem,
|
||||
sess: &Session,
|
||||
|
|
@ -524,9 +525,9 @@ pub fn cfg_matches(
|
|||
) -> bool {
|
||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||
match sess.parse_sess.check_config.expecteds.get(&cfg.name) {
|
||||
match sess.psess.check_config.expecteds.get(&cfg.name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
sess.psess.buffer_lint_with_diagnostic(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
|
|
@ -535,19 +536,19 @@ pub fn cfg_matches(
|
|||
} else {
|
||||
format!("unexpected `cfg` condition value: (none)")
|
||||
},
|
||||
BuiltinLintDiagnostics::UnexpectedCfgValue(
|
||||
BuiltinLintDiag::UnexpectedCfgValue(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
}
|
||||
None if sess.parse_sess.check_config.exhaustive_names => {
|
||||
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
sess.psess.buffer_lint_with_diagnostic(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
format!("unexpected `cfg` condition name: `{}`", cfg.name),
|
||||
BuiltinLintDiagnostics::UnexpectedCfgName(
|
||||
BuiltinLintDiag::UnexpectedCfgName(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
|
|
@ -555,7 +556,7 @@ pub fn cfg_matches(
|
|||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
sess.parse_sess.config.contains(&(cfg.name, cfg.value))
|
||||
sess.psess.config.contains(&(cfg.name, cfg.value))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -566,6 +567,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Feat
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
|
|
@ -592,13 +594,14 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
|||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
pub fn eval_condition(
|
||||
cfg: &ast::MetaItem,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = &sess.parse_sess.dcx;
|
||||
let dcx = &sess.psess.dcx;
|
||||
match &cfg.kind {
|
||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
|
|
@ -626,7 +629,7 @@ pub fn eval_condition(
|
|||
};
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.parse_sess.assume_incomplete_release {
|
||||
if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::CURRENT > min_version
|
||||
} else {
|
||||
RustcVersion::CURRENT >= min_version
|
||||
|
|
@ -984,17 +987,24 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
}
|
||||
} else if let Some((name, value)) = item.name_value_literal() {
|
||||
let mut literal_error = None;
|
||||
let mut err_span = item.span();
|
||||
if name == sym::align {
|
||||
recognised = true;
|
||||
match parse_alignment(&value.kind) {
|
||||
Ok(literal) => acc.push(ReprAlign(literal)),
|
||||
Err(message) => literal_error = Some(message),
|
||||
Err(message) => {
|
||||
err_span = value.span;
|
||||
literal_error = Some(message)
|
||||
}
|
||||
};
|
||||
} else if name == sym::packed {
|
||||
recognised = true;
|
||||
match parse_alignment(&value.kind) {
|
||||
Ok(literal) => acc.push(ReprPacked(literal)),
|
||||
Err(message) => literal_error = Some(message),
|
||||
Err(message) => {
|
||||
err_span = value.span;
|
||||
literal_error = Some(message)
|
||||
}
|
||||
};
|
||||
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
|
||||
|| int_type_of_word(name).is_some()
|
||||
|
|
@ -1007,7 +1017,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
}
|
||||
if let Some(literal_error) = literal_error {
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprGeneric {
|
||||
span: item.span(),
|
||||
span: err_span,
|
||||
repr_arg: name.to_ident_string(),
|
||||
error_part: literal_error,
|
||||
});
|
||||
|
|
@ -1039,21 +1049,37 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
});
|
||||
}
|
||||
}
|
||||
MetaItemKind::List(_) => {
|
||||
MetaItemKind::List(nested_items) => {
|
||||
if meta_item.has_name(sym::align) {
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
if nested_items.len() == 1 {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatExpectInteger {
|
||||
span: nested_items[0].span(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if meta_item.has_name(sym::packed) {
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
if nested_items.len() == 1 {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedExpectInteger {
|
||||
span: nested_items[0].span(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::Rust | sym::C | sym::simd | sym::transparent
|
||||
|
|
|
|||
|
|
@ -170,6 +170,12 @@ pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_packed_expect_integer, code = E0552)]
|
||||
pub(crate) struct IncorrectReprFormatPackedExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_repr_hint_no_paren, code = E0552)]
|
||||
|
|
@ -252,6 +258,13 @@ pub(crate) struct IncorrectReprFormatAlignOneArg {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_expect_literal_integer, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_generic, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
|
|
|
|||
|
|
@ -613,7 +613,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if self.sugg_span.is_some() {
|
||||
return;
|
||||
}
|
||||
if let hir::StmtKind::Local(hir::Local { span, ty, init: None, .. }) = &ex.kind
|
||||
|
||||
// FIXME: We make sure that this is a normal top-level binding,
|
||||
// but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern
|
||||
if let hir::StmtKind::Local(hir::Local { span, ty, init: None, pat, .. }) =
|
||||
&ex.kind
|
||||
&& let hir::PatKind::Binding(..) = pat.kind
|
||||
&& span.contains(self.decl_span)
|
||||
{
|
||||
self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
/// LL | for (key, value) in dict {
|
||||
/// | ^^^^
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
pub(super) fn add_moved_or_invoked_closure_note(
|
||||
&self,
|
||||
location: Location,
|
||||
|
|
@ -585,6 +586,7 @@ impl UseSpans<'_> {
|
|||
}
|
||||
|
||||
/// Add a span label to the arguments of the closure, if it exists.
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn args_subdiag(
|
||||
self,
|
||||
dcx: &rustc_errors::DiagCtxt,
|
||||
|
|
@ -598,6 +600,7 @@ impl UseSpans<'_> {
|
|||
|
||||
/// Add a span label to the use of the captured variable, if it exists.
|
||||
/// only adds label to the `path_span`
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn var_path_only_subdiag(
|
||||
self,
|
||||
dcx: &rustc_errors::DiagCtxt,
|
||||
|
|
@ -635,6 +638,7 @@ impl UseSpans<'_> {
|
|||
}
|
||||
|
||||
/// Add a subdiagnostic to the use of the captured variable, if it exists.
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn var_subdiag(
|
||||
self,
|
||||
dcx: &rustc_errors::DiagCtxt,
|
||||
|
|
@ -1008,6 +1012,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
self.borrow_spans(span, borrow.reserve_location)
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn explain_captures(
|
||||
&mut self,
|
||||
err: &mut Diag<'_>,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// For generic associated types (GATs) which implied 'static requirement
|
||||
// from higher-ranked trait bounds (HRTB). Try to locate span of the trait
|
||||
// and the span which bounded to the trait for adding 'static lifetime suggestion
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||
&self,
|
||||
diag: &mut Diag<'_>,
|
||||
|
|
@ -254,9 +256,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
hrtb_bounds.iter().for_each(|bound| {
|
||||
let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; };
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.span_note(
|
||||
*trait_span,
|
||||
"due to current limitations in the borrow checker, this implies a `'static` lifetime"
|
||||
|
|
@ -580,6 +579,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
/// executing...
|
||||
/// = note: ...therefore, returned references to captured variables will escape the closure
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_fnmut_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
|
|
@ -761,6 +761,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
||||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
|
||||
let ErrorConstraintInfo {
|
||||
fr,
|
||||
|
|
@ -822,6 +823,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
/// LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + 'a {
|
||||
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn add_static_impl_trait_suggestion(
|
||||
&self,
|
||||
diag: &mut Diag<'_>,
|
||||
|
|
@ -972,6 +975,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
#[instrument(skip(self, err), level = "debug")]
|
||||
fn suggest_constrain_dyn_trait_in_impl(
|
||||
&self,
|
||||
|
|
@ -1034,6 +1039,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
|
||||
let map = self.infcx.tcx.hir();
|
||||
let body_id = map.body_owned_by(self.mir_def_id());
|
||||
|
|
|
|||
|
|
@ -1066,7 +1066,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
&cause,
|
||||
param_env,
|
||||
hidden_ty.ty,
|
||||
true,
|
||||
&mut obligations,
|
||||
)?;
|
||||
|
||||
|
|
@ -1668,7 +1667,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
// (Eventually this should use const-generics, but those are not up for the task yet:
|
||||
// https://github.com/rust-lang/rust/issues/85229.)
|
||||
if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
|
||||
self.tcx().intrinsic(def_id)
|
||||
self.tcx().intrinsic(def_id).map(|i| i.name)
|
||||
{
|
||||
let idx = match name {
|
||||
sym::simd_shuffle => 2,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
|||
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
|
||||
let infcx = self.type_checker.infcx;
|
||||
debug_assert!(!infcx.next_trait_solver());
|
||||
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
|
||||
// `handle_opaque_type` cannot handle subtyping, so to support subtyping
|
||||
// we instead eagerly generalize here. This is a bit of a mess but will go
|
||||
// away once we're using the new solver.
|
||||
|
|
@ -161,8 +160,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
|||
),
|
||||
};
|
||||
let cause = ObligationCause::dummy_with_span(self.span());
|
||||
let obligations =
|
||||
infcx.handle_opaque_type(a, b, true, &cause, self.param_env())?.obligations;
|
||||
let obligations = infcx.handle_opaque_type(a, b, &cause, self.param_env())?.obligations;
|
||||
self.register_obligations(obligations);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -331,10 +329,6 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
|||
"nll::subtype"
|
||||
}
|
||||
|
||||
fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[instrument(skip(self, info), level = "trace", ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
|
|
@ -349,12 +343,15 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
|||
|
||||
debug!(?self.ambient_variance);
|
||||
// In a bivariant context this always succeeds.
|
||||
let r =
|
||||
if self.ambient_variance == ty::Variance::Bivariant { a } else { self.relate(a, b)? };
|
||||
let r = if self.ambient_variance == ty::Variance::Bivariant {
|
||||
Ok(a)
|
||||
} else {
|
||||
self.relate(a, b)
|
||||
};
|
||||
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
|
||||
Ok(r)
|
||||
r
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
|
@ -483,61 +480,59 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
|||
return Ok(ty::Binder::dummy(a));
|
||||
}
|
||||
|
||||
if self.ambient_covariance() {
|
||||
// Covariance, so we want `for<..> A <: for<..> B` --
|
||||
// therefore we compare any instantiation of A (i.e., A
|
||||
// instantiated with existentials) against every
|
||||
// instantiation of B (i.e., B instantiated with
|
||||
// universals).
|
||||
match self.ambient_variance {
|
||||
ty::Variance::Covariant => {
|
||||
// Covariance, so we want `for<..> A <: for<..> B` --
|
||||
// therefore we compare any instantiation of A (i.e., A
|
||||
// instantiated with existentials) against every
|
||||
// instantiation of B (i.e., B instantiated with
|
||||
// universals).
|
||||
|
||||
// Reset the ambient variance to covariant. This is needed
|
||||
// to correctly handle cases like
|
||||
//
|
||||
// for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32)
|
||||
//
|
||||
// Somewhat surprisingly, these two types are actually
|
||||
// **equal**, even though the one on the right looks more
|
||||
// polymorphic. The reason is due to subtyping. To see it,
|
||||
// consider that each function can call the other:
|
||||
//
|
||||
// - The left function can call the right with `'b` and
|
||||
// `'c` both equal to `'a`
|
||||
//
|
||||
// - The right function can call the left with `'a` set to
|
||||
// `{P}`, where P is the point in the CFG where the call
|
||||
// itself occurs. Note that `'b` and `'c` must both
|
||||
// include P. At the point, the call works because of
|
||||
// subtyping (i.e., `&'b u32 <: &{P} u32`).
|
||||
let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant);
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
self.enter_forall(b, |this, b| {
|
||||
let a = this.instantiate_binder_with_existentials(a);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
}
|
||||
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
self.enter_forall(b, |this, b| {
|
||||
let a = this.instantiate_binder_with_existentials(a);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
ty::Variance::Contravariant => {
|
||||
// Contravariance, so we want `for<..> A :> for<..> B` --
|
||||
// therefore we compare every instantiation of A (i.e., A
|
||||
// instantiated with universals) against any
|
||||
// instantiation of B (i.e., B instantiated with
|
||||
// existentials). Opposite of above.
|
||||
|
||||
self.ambient_variance = variance;
|
||||
}
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
self.enter_forall(a, |this, a| {
|
||||
let b = this.instantiate_binder_with_existentials(b);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
}
|
||||
|
||||
if self.ambient_contravariance() {
|
||||
// Contravariance, so we want `for<..> A :> for<..> B`
|
||||
// -- therefore we compare every instantiation of A (i.e.,
|
||||
// A instantiated with universals) against any
|
||||
// instantiation of B (i.e., B instantiated with
|
||||
// existentials). Opposite of above.
|
||||
ty::Variance::Invariant => {
|
||||
// Invariant, so we want `for<..> A == for<..> B` --
|
||||
// therefore we want `exists<..> A == for<..> B` and
|
||||
// `exists<..> B == for<..> A`.
|
||||
//
|
||||
// See the comment in `fn Equate::binders` for more details.
|
||||
|
||||
// Reset ambient variance to contravariance. See the
|
||||
// covariant case above for an explanation.
|
||||
let variance =
|
||||
std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
self.enter_forall(b, |this, b| {
|
||||
let a = this.instantiate_binder_with_existentials(a);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
self.enter_forall(a, |this, a| {
|
||||
let b = this.instantiate_binder_with_existentials(b);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
}
|
||||
|
||||
self.enter_forall(a, |this, a| {
|
||||
let b = this.instantiate_binder_with_existentials(b);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
|
||||
self.ambient_variance = variance;
|
||||
ty::Variance::Bivariant => {}
|
||||
}
|
||||
|
||||
Ok(a)
|
||||
|
|
@ -581,10 +576,6 @@ impl<'bccx, 'tcx> ObligationEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx
|
|||
);
|
||||
}
|
||||
|
||||
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
|
||||
unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance")
|
||||
}
|
||||
|
||||
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
|
||||
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
|
||||
|
|
|
|||
|
|
@ -221,12 +221,6 @@ builtin_macros_requires_cfg_pattern =
|
|||
macro requires a cfg-pattern as an argument
|
||||
.label = cfg-pattern required
|
||||
|
||||
builtin_macros_should_panic = functions using `#[should_panic]` must return `()`
|
||||
|
||||
builtin_macros_test_arg_non_lifetime = functions used as tests can not have any non-lifetime generic parameters
|
||||
|
||||
builtin_macros_test_args = functions used as tests can not have any arguments
|
||||
|
||||
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
|
||||
.label = `{$kind}` because of this
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use rustc_index::bit_set::GrowableBitSet;
|
|||
use rustc_parse::parser::Parser;
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_session::lint;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, InnerSpan, Span};
|
||||
|
|
@ -36,19 +35,17 @@ fn parse_args<'a>(
|
|||
is_global_asm: bool,
|
||||
) -> PResult<'a, AsmArgs> {
|
||||
let mut p = ecx.new_parser_from_tts(tts);
|
||||
let sess = &ecx.sess.parse_sess;
|
||||
parse_asm_args(&mut p, sess, sp, is_global_asm)
|
||||
parse_asm_args(&mut p, sp, is_global_asm)
|
||||
}
|
||||
|
||||
// Primarily public for rustfmt consumption.
|
||||
// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
|
||||
pub fn parse_asm_args<'a>(
|
||||
p: &mut Parser<'a>,
|
||||
sess: &'a ParseSess,
|
||||
sp: Span,
|
||||
is_global_asm: bool,
|
||||
) -> PResult<'a, AsmArgs> {
|
||||
let dcx = &sess.dcx;
|
||||
let dcx = &p.psess.dcx;
|
||||
|
||||
if p.token == token::Eof {
|
||||
return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
|
||||
|
|
@ -299,7 +296,7 @@ pub fn parse_asm_args<'a>(
|
|||
fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
|
||||
// Tool-only output
|
||||
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
|
||||
p.sess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
|
||||
p.psess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
|
||||
}
|
||||
|
||||
/// Try to set the provided option in the provided `AsmArgs`.
|
||||
|
|
@ -371,7 +368,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
|
|||
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
return Err(p.sess.dcx.create_err(errors::NonABI { span: p.token.span }));
|
||||
return Err(p.psess.dcx.create_err(errors::NonABI { span: p.token.span }));
|
||||
}
|
||||
|
||||
let mut new_abis = Vec::new();
|
||||
|
|
@ -382,7 +379,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
|
|||
}
|
||||
Err(opt_lit) => {
|
||||
let span = opt_lit.map_or(p.token.span, |lit| lit.span);
|
||||
let mut err = p.sess.dcx.struct_span_err(span, "expected string literal");
|
||||
let mut err = p.psess.dcx.struct_span_err(span, "expected string literal");
|
||||
err.span_label(span, "not a string literal");
|
||||
return Err(err);
|
||||
}
|
||||
|
|
@ -498,7 +495,7 @@ fn expand_preparsed_asm(
|
|||
};
|
||||
|
||||
if template_str.contains(".intel_syntax") {
|
||||
ecx.parse_sess().buffer_lint(
|
||||
ecx.psess().buffer_lint(
|
||||
lint::builtin::BAD_ASM_STYLE,
|
||||
find_span(".intel_syntax"),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
|
|
@ -506,7 +503,7 @@ fn expand_preparsed_asm(
|
|||
);
|
||||
}
|
||||
if template_str.contains(".att_syntax") {
|
||||
ecx.parse_sess().buffer_lint(
|
||||
ecx.psess().buffer_lint(
|
||||
lint::builtin::BAD_ASM_STYLE,
|
||||
find_span(".att_syntax"),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl MultiItemModifier for Expander {
|
|||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&ecx.sess.parse_sess,
|
||||
&ecx.sess.psess,
|
||||
meta_item,
|
||||
ast::AttrStyle::Outer,
|
||||
sym::cfg_accessible,
|
||||
|
|
|
|||
|
|
@ -195,8 +195,7 @@ impl CfgEval<'_, '_> {
|
|||
// Re-parse the tokens, setting the `capture_cfg` flag to save extra information
|
||||
// to the captured `AttrTokenStream` (specifically, we capture
|
||||
// `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
|
||||
let mut parser =
|
||||
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
|
||||
let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.psess, orig_tokens, None);
|
||||
parser.capture_cfg = true;
|
||||
match parse_annotatable_with(&mut parser) {
|
||||
Ok(a) => annotatable = a,
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use rustc_ast::{self as ast, AttrItem, AttrStyle};
|
|||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::FileName;
|
||||
|
||||
pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) {
|
||||
pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
||||
for raw_attr in attrs {
|
||||
let mut parser = rustc_parse::new_parser_from_source_str(
|
||||
parse_sess,
|
||||
psess,
|
||||
FileName::cli_crate_attr_source_code(raw_attr),
|
||||
raw_attr.clone(),
|
||||
);
|
||||
|
|
@ -25,12 +25,12 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
|
|||
};
|
||||
let end_span = parser.token.span;
|
||||
if parser.token != token::Eof {
|
||||
parse_sess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
|
||||
psess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
|
||||
continue;
|
||||
}
|
||||
|
||||
krate.attrs.push(mk_attr(
|
||||
&parse_sess.attr_id_generator,
|
||||
&psess.attr_id_generator,
|
||||
AttrStyle::Inner,
|
||||
path,
|
||||
args,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub fn expand_concat(
|
|||
guar = Some(guarantee);
|
||||
}
|
||||
Err(err) => {
|
||||
guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span));
|
||||
guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span));
|
||||
}
|
||||
},
|
||||
// We also want to allow negative numeric literals.
|
||||
|
|
@ -52,7 +52,7 @@ pub fn expand_concat(
|
|||
Ok(LitKind::Int(i, _)) => accumulator.push_str(&format!("-{i}")),
|
||||
Ok(LitKind::Float(f, _)) => accumulator.push_str(&format!("-{f}")),
|
||||
Err(err) => {
|
||||
guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span));
|
||||
guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span));
|
||||
}
|
||||
_ => missing_literal.push(e.span),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ fn invalid_type_err(
|
|||
Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }),
|
||||
Ok(LitKind::ByteStr(..) | LitKind::Byte(_)) => unreachable!(),
|
||||
Ok(LitKind::Err(guar)) => guar,
|
||||
Err(err) => report_lit_error(&cx.sess.parse_sess, err, token_lit, span),
|
||||
Err(err) => report_lit_error(&cx.sess.psess, err, token_lit, span),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ impl MultiItemModifier for Expander {
|
|||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&sess.parse_sess,
|
||||
&sess.psess,
|
||||
meta_item,
|
||||
ast::AttrStyle::Outer,
|
||||
sym::derive,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use crate::deriving::generic::ty::*;
|
|||
use crate::deriving::generic::*;
|
||||
use crate::errors;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::{attr, walk_list, EnumDef, VariantData};
|
||||
use rustc_ast::visit::walk_list;
|
||||
use rustc_ast::{attr, EnumDef, VariantData};
|
||||
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
|
|
|
|||
|
|
@ -601,11 +601,7 @@ impl<'a> TraitDef<'a> {
|
|||
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
generics: Generics::default(),
|
||||
where_clauses: (
|
||||
ast::TyAliasWhereClause::default(),
|
||||
ast::TyAliasWhereClause::default(),
|
||||
),
|
||||
where_predicates_split: 0,
|
||||
where_clauses: ast::TyAliasWhereClauses::default(),
|
||||
bounds: Vec::new(),
|
||||
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
|
||||
})),
|
||||
|
|
@ -1607,9 +1603,10 @@ impl<'a> TraitDef<'a> {
|
|||
// Once use of `icu4x-0.9.0` has dropped sufficiently, this
|
||||
// exception should be removed.
|
||||
let is_simple_path = |ty: &P<ast::Ty>, sym| {
|
||||
if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind &&
|
||||
let [seg] = segments.as_slice() &&
|
||||
seg.ident.name == sym && seg.args.is_none()
|
||||
if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind
|
||||
&& let [seg] = segments.as_slice()
|
||||
&& seg.ident.name == sym
|
||||
&& seg.args.is_none()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
|
|
@ -1617,8 +1614,8 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind &&
|
||||
is_simple_path(ty, sym::u8)
|
||||
let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind
|
||||
&& is_simple_path(ty, sym::u8)
|
||||
{
|
||||
Some("byte")
|
||||
} else if is_simple_path(&struct_field.ty, sym::str) {
|
||||
|
|
@ -1628,14 +1625,14 @@ impl<'a> TraitDef<'a> {
|
|||
};
|
||||
|
||||
if let Some(ty) = exception {
|
||||
cx.sess.parse_sess.buffer_lint_with_diagnostic(
|
||||
cx.sess.psess.buffer_lint_with_diagnostic(
|
||||
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
|
||||
sp,
|
||||
ast::CRATE_NODE_ID,
|
||||
format!(
|
||||
"{ty} slice in a packed struct that derives a built-in trait"
|
||||
),
|
||||
rustc_lint_defs::BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive
|
||||
rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive,
|
||||
);
|
||||
} else {
|
||||
// Wrap the expression in `{...}`, causing a copy.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub fn expand_option_env<'cx>(
|
|||
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
let value = lookup_env(cx, var);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
cx.sess.psess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
|
||||
|
|
@ -94,7 +94,7 @@ pub fn expand_env<'cx>(
|
|||
|
||||
let span = cx.with_def_site_ctxt(sp);
|
||||
let value = lookup_env(cx, var);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
cx.sess.psess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
let ExprKind::Lit(token::Lit {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
|
||||
SingleLabelManySpans, SubdiagnosticMessageOp,
|
||||
SingleLabelManySpans, SubdiagMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
|
@ -590,7 +590,7 @@ pub(crate) struct FormatUnusedArg {
|
|||
// Allow the singular form to be a subdiagnostic of the multiple-unused
|
||||
// form of diagnostic.
|
||||
impl AddToDiagnostic for FormatUnusedArg {
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
|
||||
fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_span::symbol::{Ident, Symbol};
|
|||
use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span};
|
||||
|
||||
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
|
||||
|
||||
// The format_args!() macro is expanded in three steps:
|
||||
// 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
|
||||
|
|
@ -553,7 +553,7 @@ fn make_format_args(
|
|||
msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
|
||||
node_id: rustc_ast::CRATE_NODE_ID,
|
||||
lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY),
|
||||
diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
|
||||
diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally {
|
||||
position_sp_to_replace,
|
||||
position_sp_for_msg,
|
||||
named_arg_sp: arg_name.span,
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ pub fn expand_include<'cx>(
|
|||
return DummyResult::any(sp, guar);
|
||||
}
|
||||
};
|
||||
let p = new_parser_from_file(cx.parse_sess(), &file, Some(sp));
|
||||
let p = new_parser_from_file(cx.psess(), &file, Some(sp));
|
||||
|
||||
// If in the included file we have e.g., `mod bar;`,
|
||||
// then the path of `bar.rs` should be relative to the directory of `file`.
|
||||
|
|
@ -136,7 +136,7 @@ pub fn expand_include<'cx>(
|
|||
fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
|
||||
let expr = parse_expr(&mut self.p).ok()?;
|
||||
if self.p.token != token::Eof {
|
||||
self.p.sess.buffer_lint(
|
||||
self.p.psess.buffer_lint(
|
||||
INCOMPLETE_INCLUDE,
|
||||
self.p.token.span,
|
||||
self.node_id,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub fn inject(
|
|||
features: &Features,
|
||||
) -> usize {
|
||||
let orig_num_items = krate.items.len();
|
||||
let edition = sess.parse_sess.edition;
|
||||
let edition = sess.psess.edition;
|
||||
|
||||
// the first name in this list is the crate name of the crate with the prelude
|
||||
let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ struct InnerItemLinter<'a> {
|
|||
impl<'a> Visitor<'a> for InnerItemLinter<'_> {
|
||||
fn visit_item(&mut self, i: &'a ast::Item) {
|
||||
if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) {
|
||||
self.sess.parse_sess.buffer_lint(
|
||||
self.sess.psess.buffer_lint(
|
||||
UNNAMEABLE_TEST_ITEMS,
|
||||
attr.span,
|
||||
i.id,
|
||||
|
|
@ -200,7 +200,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
|||
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
|
||||
item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
|
||||
let allow_dead_code = attr::mk_attr_nested_word(
|
||||
&self.sess.parse_sess.attr_id_generator,
|
||||
&self.sess.psess.attr_id_generator,
|
||||
ast::AttrStyle::Outer,
|
||||
sym::allow,
|
||||
sym::dead_code,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na
|
|||
// All the built-in macro attributes are "words" at the moment.
|
||||
let template = AttributeTemplate { word: true, ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&ecx.sess.parse_sess,
|
||||
&ecx.sess.psess,
|
||||
meta_item,
|
||||
AttrStyle::Outer,
|
||||
name,
|
||||
|
|
@ -37,7 +37,7 @@ pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name:
|
|||
};
|
||||
if let Some(attrs) = attrs {
|
||||
if let Some(attr) = attr::find_by_name(attrs, name) {
|
||||
ecx.parse_sess().buffer_lint(
|
||||
ecx.psess().buffer_lint(
|
||||
DUPLICATE_MACRO_ATTRIBUTES,
|
||||
attr.span,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
|
|
|
|||
|
|
@ -525,8 +525,11 @@ pub struct Unique<T: ?Sized> {
|
|||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[lang = "global_alloc_ty"]
|
||||
pub struct Global;
|
||||
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T: ?Sized, A = ()>(Unique<T>, A);
|
||||
pub struct Box<T: ?Sized, A = Global>(Unique<T>, A);
|
||||
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
|
||||
|
||||
|
|
@ -536,7 +539,7 @@ impl<T> Box<T> {
|
|||
let size = intrinsics::size_of::<T>();
|
||||
let ptr = libc::malloc(size);
|
||||
intrinsics::copy(&val as *const T as *const u8, ptr, size);
|
||||
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, ())
|
||||
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,10 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
|
|||
Integer::I64 => types::I64,
|
||||
Integer::I128 => types::I128,
|
||||
},
|
||||
Primitive::F16 => unimplemented!("f16_f128"),
|
||||
Primitive::F32 => types::F32,
|
||||
Primitive::F64 => types::F64,
|
||||
Primitive::F128 => unimplemented!("f16_f128"),
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Primitive::Pointer(_) => pointer_ty(tcx),
|
||||
}
|
||||
|
|
@ -61,8 +63,10 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
|
|||
},
|
||||
ty::Char => types::I32,
|
||||
ty::Float(size) => match size {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => types::F32,
|
||||
FloatTy::F64 => types::F64,
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
},
|
||||
ty::FnPtr(_) => pointer_ty(tcx),
|
||||
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
|
||||
|
|
|
|||
|
|
@ -1255,7 +1255,17 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
|
||||
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
|
||||
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
|
||||
_ => return Err(Instance::new(instance.def_id(), instance.args)),
|
||||
_ => {
|
||||
let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
|
||||
if intrinsic.must_be_overridden {
|
||||
span_bug!(
|
||||
source_info.span,
|
||||
"intrinsic {} must be overridden by codegen_cranelift, but isn't",
|
||||
intrinsic.name,
|
||||
);
|
||||
}
|
||||
return Err(Instance::new(instance.def_id(), instance.args));
|
||||
}
|
||||
}
|
||||
|
||||
let ret_block = fx.get_block(destination.unwrap());
|
||||
|
|
|
|||
|
|
@ -74,10 +74,6 @@ fn unsize_ptr<'tcx>(
|
|||
| (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
|
||||
(src, unsized_info(fx, *a, *b, old_info))
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
|
||||
let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty());
|
||||
(src, unsized_info(fx, a, b, old_info))
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
|
|
|
|||
|
|
@ -472,6 +472,7 @@ pub trait Allocator {
|
|||
|
||||
impl Allocator for () {}
|
||||
|
||||
#[lang = "global_alloc_ty"]
|
||||
pub struct Global;
|
||||
|
||||
impl Allocator for Global {}
|
||||
|
|
|
|||
|
|
@ -834,10 +834,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
|
||||
let b_offset = a.size(self).align_to(b.align(self).abi);
|
||||
let pair_type = place.layout.gcc_type(self);
|
||||
|
||||
let mut load = |i, scalar: &abi::Scalar, align| {
|
||||
let llptr = self.struct_gep(pair_type, place.llval, i as u64);
|
||||
let llptr = if i == 0 {
|
||||
place.llval
|
||||
} else {
|
||||
self.inbounds_ptradd(place.llval, self.const_usize(b_offset.bytes()))
|
||||
};
|
||||
let llty = place.layout.scalar_pair_element_gcc_type(self, i);
|
||||
let load = self.load(llty, llptr, align);
|
||||
scalar_load_metadata(self, load, scalar);
|
||||
|
|
@ -971,33 +974,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
result.get_address(None)
|
||||
}
|
||||
|
||||
fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
|
||||
// FIXME(antoyo): it would be better if the API only called this on struct, not on arrays.
|
||||
assert_eq!(idx as usize as u64, idx);
|
||||
let value = ptr.dereference(None).to_rvalue();
|
||||
|
||||
if value_type.dyncast_array().is_some() {
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
let element = self.context.new_array_access(None, value, index);
|
||||
element.get_address(None)
|
||||
}
|
||||
else if let Some(vector_type) = value_type.dyncast_vector() {
|
||||
let array_type = vector_type.get_element_type().make_pointer();
|
||||
let array = self.bitcast(ptr, array_type);
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
let element = self.context.new_array_access(None, array, index);
|
||||
element.get_address(None)
|
||||
}
|
||||
else if let Some(struct_type) = value_type.is_struct() {
|
||||
// NOTE: due to opaque pointers now being used, we need to bitcast here.
|
||||
let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer());
|
||||
ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None)
|
||||
}
|
||||
else {
|
||||
panic!("Unexpected type {:?}", value_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Casts */
|
||||
fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): check that it indeed truncate the value.
|
||||
|
|
|
|||
|
|
@ -83,8 +83,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
|
||||
pub fn type_float_from_ty(&self, t: ty::FloatTy) -> Type<'gcc> {
|
||||
match t {
|
||||
ty::FloatTy::F16 => self.type_f16(),
|
||||
ty::FloatTy::F32 => self.type_f32(),
|
||||
ty::FloatTy::F64 => self.type_f64(),
|
||||
ty::FloatTy::F128 => self.type_f128(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,6 +120,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
self.isize_type
|
||||
}
|
||||
|
||||
fn type_f16(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> Type<'gcc> {
|
||||
self.float_type
|
||||
}
|
||||
|
|
@ -125,6 +131,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
fn type_f64(&self) -> Type<'gcc> {
|
||||
self.double_type
|
||||
}
|
||||
|
||||
fn type_f128(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
}
|
||||
|
||||
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
||||
self.context.new_function_pointer_type(None, return_type, params, false)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::{self, Abi, Align, F16, F128, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
|
|
@ -151,7 +151,6 @@ pub trait LayoutGccExt<'tcx> {
|
|||
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||
fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>;
|
||||
fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc>;
|
||||
fn gcc_field_index(&self, index: usize) -> u64;
|
||||
fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
||||
}
|
||||
|
||||
|
|
@ -257,8 +256,10 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
match scalar.primitive() {
|
||||
Int(i, true) => cx.type_from_integer(i),
|
||||
Int(i, false) => cx.type_from_unsigned_integer(i),
|
||||
F16 => cx.type_f16(),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
F128 => cx.type_f128(),
|
||||
Pointer(address_space) => {
|
||||
// If we know the alignment, pick something better than i8.
|
||||
let pointee =
|
||||
|
|
@ -304,24 +305,6 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
self.scalar_gcc_type_at(cx, scalar, offset)
|
||||
}
|
||||
|
||||
fn gcc_field_index(&self, index: usize) -> u64 {
|
||||
match self.abi {
|
||||
Abi::Scalar(_) | Abi::ScalarPair(..) => {
|
||||
bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match self.fields {
|
||||
FieldsShape::Primitive | FieldsShape::Union(_) => {
|
||||
bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
FieldsShape::Array { .. } => index as u64,
|
||||
|
||||
FieldsShape::Arbitrary { .. } => 1 + (self.fields.memory_index(index) as u64) * 2,
|
||||
}
|
||||
}
|
||||
|
||||
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo> {
|
||||
if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
|
||||
return pointee;
|
||||
|
|
@ -351,10 +334,6 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
layout.is_gcc_scalar_pair()
|
||||
}
|
||||
|
||||
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 {
|
||||
layout.gcc_field_index(index)
|
||||
}
|
||||
|
||||
fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, _immediate: bool) -> Type<'gcc> {
|
||||
layout.scalar_pair_element_gcc_type(self, index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -519,12 +519,22 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
let pgo_sample_use_path = get_pgo_sample_use_path(config);
|
||||
let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
|
||||
let instr_profile_output_path = get_instr_profile_output_path(config);
|
||||
let sanitize_dataflow_abilist: Vec<_> = config
|
||||
.sanitizer_dataflow_abilist
|
||||
.iter()
|
||||
.map(|file| CString::new(file.as_str()).unwrap())
|
||||
.collect();
|
||||
let sanitize_dataflow_abilist_ptrs: Vec<_> =
|
||||
sanitize_dataflow_abilist.iter().map(|file| file.as_ptr()).collect();
|
||||
// Sanitizer instrumentation is only inserted during the pre-link optimization stage.
|
||||
let sanitizer_options = if !is_lto {
|
||||
Some(llvm::SanitizerOptions {
|
||||
sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
|
||||
sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
|
||||
sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI),
|
||||
sanitize_dataflow: config.sanitizer.contains(SanitizerSet::DATAFLOW),
|
||||
sanitize_dataflow_abilist: sanitize_dataflow_abilist_ptrs.as_ptr(),
|
||||
sanitize_dataflow_abilist_len: sanitize_dataflow_abilist_ptrs.len(),
|
||||
sanitize_kcfi: config.sanitizer.contains(SanitizerSet::KCFI),
|
||||
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
|
||||
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
abi::F32 | abi::F64 => {}
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,11 +603,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
let llptr = if i == 0 {
|
||||
place.llval
|
||||
} else {
|
||||
self.inbounds_gep(
|
||||
self.type_i8(),
|
||||
place.llval,
|
||||
&[self.const_usize(b_offset.bytes())],
|
||||
)
|
||||
self.inbounds_ptradd(place.llval, self.const_usize(b_offset.bytes()))
|
||||
};
|
||||
let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
|
||||
let load = self.load(llty, llptr, align);
|
||||
|
|
@ -778,11 +774,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn struct_gep(&mut self, ty: &'ll Type, ptr: &'ll Value, idx: u64) -> &'ll Value {
|
||||
assert_eq!(idx as c_uint as u64, idx);
|
||||
unsafe { llvm::LLVMBuildStructGEP2(self.llbuilder, ty, ptr, idx as c_uint, UNNAMED) }
|
||||
}
|
||||
|
||||
/* Casts */
|
||||
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) }
|
||||
|
|
|
|||
|
|
@ -685,8 +685,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let t_i64 = self.type_i64();
|
||||
let t_i128 = self.type_i128();
|
||||
let t_isize = self.type_isize();
|
||||
let t_f16 = self.type_f16();
|
||||
let t_f32 = self.type_f32();
|
||||
let t_f64 = self.type_f64();
|
||||
let t_f128 = self.type_f128();
|
||||
let t_metadata = self.type_metadata();
|
||||
let t_token = self.type_token();
|
||||
|
||||
|
|
@ -728,69 +730,115 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
ifn!("llvm.debugtrap", fn() -> void);
|
||||
ifn!("llvm.frameaddress", fn(t_i32) -> ptr);
|
||||
|
||||
ifn!("llvm.powi.f16", fn(t_f16, t_i32) -> t_f16);
|
||||
ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
|
||||
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
||||
ifn!("llvm.powi.f128", fn(t_f128, t_i32) -> t_f128);
|
||||
|
||||
ifn!("llvm.pow.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.pow.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.sqrt.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.sqrt.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.sin.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.sin.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.cos.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.cos.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.exp.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.exp.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.exp2.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.exp2.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.log.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.log.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.log10.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.log10.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.log2.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.log2.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.fma.f16", fn(t_f16, t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.fabs.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.minnum.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.floor.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.floor.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.ceil.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.ceil.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.trunc.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.trunc.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.copysign.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.copysign.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.round.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.round.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.roundeven.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.roundeven.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.roundeven.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.rint.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.rint.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.nearbyint.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
|
||||
ifn!("llvm.nearbyint.f128", fn(t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
|
||||
ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
|
||||
|
|
|
|||
|
|
@ -357,31 +357,27 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
|
|||
|
||||
let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics();
|
||||
|
||||
let eligible_def_ids: Vec<DefId> = tcx
|
||||
.mir_keys(())
|
||||
.iter()
|
||||
.filter_map(|local_def_id| {
|
||||
let def_id = local_def_id.to_def_id();
|
||||
let kind = tcx.def_kind(def_id);
|
||||
// `mir_keys` will give us `DefId`s for all kinds of things, not
|
||||
// just "functions", like consts, statics, etc. Filter those out.
|
||||
// If `ignore_unused_generics` was specified, filter out any
|
||||
// generic functions from consideration as well.
|
||||
if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) {
|
||||
return None;
|
||||
}
|
||||
if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) {
|
||||
return None;
|
||||
}
|
||||
Some(local_def_id.to_def_id())
|
||||
})
|
||||
.collect();
|
||||
let eligible_def_ids = tcx.mir_keys(()).iter().filter_map(|local_def_id| {
|
||||
let def_id = local_def_id.to_def_id();
|
||||
let kind = tcx.def_kind(def_id);
|
||||
// `mir_keys` will give us `DefId`s for all kinds of things, not
|
||||
// just "functions", like consts, statics, etc. Filter those out.
|
||||
// If `ignore_unused_generics` was specified, filter out any
|
||||
// generic functions from consideration as well.
|
||||
if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) {
|
||||
return None;
|
||||
}
|
||||
if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) {
|
||||
return None;
|
||||
}
|
||||
Some(local_def_id.to_def_id())
|
||||
});
|
||||
|
||||
let codegenned_def_ids = codegenned_and_inlined_items(tcx);
|
||||
|
||||
// For each `DefId` that should have coverage instrumentation but wasn't
|
||||
// codegenned, add it to the function coverage map as an unused function.
|
||||
for def_id in eligible_def_ids.into_iter().filter(|id| !codegenned_def_ids.contains(id)) {
|
||||
for def_id in eligible_def_ids.filter(|id| !codegenned_def_ids.contains(id)) {
|
||||
// Skip any function that didn't have coverage data added to it by the
|
||||
// coverage instrumentor.
|
||||
let body = tcx.instance_mir(ty::InstanceDef::Item(def_id));
|
||||
|
|
|
|||
|
|
@ -454,9 +454,13 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
|
|||
ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
|
||||
build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id)
|
||||
}
|
||||
// Box<T, A> may have a non-1-ZST allocator A. In that case, we
|
||||
// cannot treat Box<T, A> as just an owned alias of `*mut T`.
|
||||
ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_1zst() => {
|
||||
// Some `Box` are newtyped pointers, make debuginfo aware of that.
|
||||
// Only works if the allocator argument is a 1-ZST and hence irrelevant for layout
|
||||
// (or if there is no allocator argument).
|
||||
ty::Adt(def, args)
|
||||
if def.is_box()
|
||||
&& args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
|
||||
{
|
||||
build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
|
||||
|
|
@ -695,9 +699,13 @@ impl MsvcBasicName for ty::UintTy {
|
|||
|
||||
impl MsvcBasicName for ty::FloatTy {
|
||||
fn msvc_basic_name(self) -> &'static str {
|
||||
// FIXME: f16 and f128 have no MSVC representation. We could improve the debuginfo.
|
||||
// See: <https://github.com/rust-lang/rust/pull/114607/files#r1454683264>
|
||||
match self {
|
||||
ty::FloatTy::F16 => "half",
|
||||
ty::FloatTy::F32 => "float",
|
||||
ty::FloatTy::F64 => "double",
|
||||
ty::FloatTy::F128 => "fp128",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,8 +122,10 @@ fn tag_base_type<'ll, 'tcx>(
|
|||
// Niche tags are always normalized to unsized integers of the correct size.
|
||||
match tag.primitive() {
|
||||
Primitive::Int(t, _) => t,
|
||||
Primitive::F16 => Integer::I16,
|
||||
Primitive::F32 => Integer::I32,
|
||||
Primitive::F64 => Integer::I64,
|
||||
Primitive::F128 => Integer::I128,
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Primitive::Pointer(_) => {
|
||||
// If the niche is the NULL value of a reference, then `discr_enum_ty` will be
|
||||
|
|
|
|||
|
|
@ -28,51 +28,118 @@ fn get_simple_intrinsic<'ll>(
|
|||
name: Symbol,
|
||||
) -> Option<(&'ll Type, &'ll Value)> {
|
||||
let llvm_name = match name {
|
||||
sym::sqrtf16 => "llvm.sqrt.f16",
|
||||
sym::sqrtf32 => "llvm.sqrt.f32",
|
||||
sym::sqrtf64 => "llvm.sqrt.f64",
|
||||
sym::sqrtf128 => "llvm.sqrt.f128",
|
||||
|
||||
sym::powif16 => "llvm.powi.f16",
|
||||
sym::powif32 => "llvm.powi.f32",
|
||||
sym::powif64 => "llvm.powi.f64",
|
||||
sym::powif128 => "llvm.powi.f128",
|
||||
|
||||
sym::sinf16 => "llvm.sin.f16",
|
||||
sym::sinf32 => "llvm.sin.f32",
|
||||
sym::sinf64 => "llvm.sin.f64",
|
||||
sym::sinf128 => "llvm.sin.f128",
|
||||
|
||||
sym::cosf16 => "llvm.cos.f16",
|
||||
sym::cosf32 => "llvm.cos.f32",
|
||||
sym::cosf64 => "llvm.cos.f64",
|
||||
sym::cosf128 => "llvm.cos.f128",
|
||||
|
||||
sym::powf16 => "llvm.pow.f16",
|
||||
sym::powf32 => "llvm.pow.f32",
|
||||
sym::powf64 => "llvm.pow.f64",
|
||||
sym::powf128 => "llvm.pow.f128",
|
||||
|
||||
sym::expf16 => "llvm.exp.f16",
|
||||
sym::expf32 => "llvm.exp.f32",
|
||||
sym::expf64 => "llvm.exp.f64",
|
||||
sym::expf128 => "llvm.exp.f128",
|
||||
|
||||
sym::exp2f16 => "llvm.exp2.f16",
|
||||
sym::exp2f32 => "llvm.exp2.f32",
|
||||
sym::exp2f64 => "llvm.exp2.f64",
|
||||
sym::exp2f128 => "llvm.exp2.f128",
|
||||
|
||||
sym::logf16 => "llvm.log.f16",
|
||||
sym::logf32 => "llvm.log.f32",
|
||||
sym::logf64 => "llvm.log.f64",
|
||||
sym::logf128 => "llvm.log.f128",
|
||||
|
||||
sym::log10f16 => "llvm.log10.f16",
|
||||
sym::log10f32 => "llvm.log10.f32",
|
||||
sym::log10f64 => "llvm.log10.f64",
|
||||
sym::log10f128 => "llvm.log10.f128",
|
||||
|
||||
sym::log2f16 => "llvm.log2.f16",
|
||||
sym::log2f32 => "llvm.log2.f32",
|
||||
sym::log2f64 => "llvm.log2.f64",
|
||||
sym::log2f128 => "llvm.log2.f128",
|
||||
|
||||
sym::fmaf16 => "llvm.fma.f16",
|
||||
sym::fmaf32 => "llvm.fma.f32",
|
||||
sym::fmaf64 => "llvm.fma.f64",
|
||||
sym::fmaf128 => "llvm.fma.f128",
|
||||
|
||||
sym::fabsf16 => "llvm.fabs.f16",
|
||||
sym::fabsf32 => "llvm.fabs.f32",
|
||||
sym::fabsf64 => "llvm.fabs.f64",
|
||||
sym::fabsf128 => "llvm.fabs.f128",
|
||||
|
||||
sym::minnumf16 => "llvm.minnum.f16",
|
||||
sym::minnumf32 => "llvm.minnum.f32",
|
||||
sym::minnumf64 => "llvm.minnum.f64",
|
||||
sym::minnumf128 => "llvm.minnum.f128",
|
||||
|
||||
sym::maxnumf16 => "llvm.maxnum.f16",
|
||||
sym::maxnumf32 => "llvm.maxnum.f32",
|
||||
sym::maxnumf64 => "llvm.maxnum.f64",
|
||||
sym::maxnumf128 => "llvm.maxnum.f128",
|
||||
|
||||
sym::copysignf16 => "llvm.copysign.f16",
|
||||
sym::copysignf32 => "llvm.copysign.f32",
|
||||
sym::copysignf64 => "llvm.copysign.f64",
|
||||
sym::copysignf128 => "llvm.copysign.f128",
|
||||
|
||||
sym::floorf16 => "llvm.floor.f16",
|
||||
sym::floorf32 => "llvm.floor.f32",
|
||||
sym::floorf64 => "llvm.floor.f64",
|
||||
sym::floorf128 => "llvm.floor.f128",
|
||||
|
||||
sym::ceilf16 => "llvm.ceil.f16",
|
||||
sym::ceilf32 => "llvm.ceil.f32",
|
||||
sym::ceilf64 => "llvm.ceil.f64",
|
||||
sym::ceilf128 => "llvm.ceil.f128",
|
||||
|
||||
sym::truncf16 => "llvm.trunc.f16",
|
||||
sym::truncf32 => "llvm.trunc.f32",
|
||||
sym::truncf64 => "llvm.trunc.f64",
|
||||
sym::truncf128 => "llvm.trunc.f128",
|
||||
|
||||
sym::rintf16 => "llvm.rint.f16",
|
||||
sym::rintf32 => "llvm.rint.f32",
|
||||
sym::rintf64 => "llvm.rint.f64",
|
||||
sym::rintf128 => "llvm.rint.f128",
|
||||
|
||||
sym::nearbyintf16 => "llvm.nearbyint.f16",
|
||||
sym::nearbyintf32 => "llvm.nearbyint.f32",
|
||||
sym::nearbyintf64 => "llvm.nearbyint.f64",
|
||||
sym::nearbyintf128 => "llvm.nearbyint.f128",
|
||||
|
||||
sym::roundf16 => "llvm.round.f16",
|
||||
sym::roundf32 => "llvm.round.f32",
|
||||
sym::roundf64 => "llvm.round.f64",
|
||||
sym::roundf128 => "llvm.round.f128",
|
||||
|
||||
sym::ptr_mask => "llvm.ptrmask",
|
||||
|
||||
sym::roundevenf16 => "llvm.roundeven.f16",
|
||||
sym::roundevenf32 => "llvm.roundeven.f32",
|
||||
sym::roundevenf64 => "llvm.roundeven.f64",
|
||||
sym::roundevenf128 => "llvm.roundeven.f128",
|
||||
|
||||
_ => return None,
|
||||
};
|
||||
Some(cx.get_intrinsic(llvm_name))
|
||||
|
|
@ -163,11 +230,15 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
emit_va_arg(self, args[0], ret_ty)
|
||||
}
|
||||
}
|
||||
Primitive::F16 => bug!("the va_arg intrinsic does not work with `f16`"),
|
||||
Primitive::F64 | Primitive::Pointer(_) => {
|
||||
emit_va_arg(self, args[0], ret_ty)
|
||||
}
|
||||
// `va_arg` should never be used with the return type f32.
|
||||
Primitive::F32 => bug!("the va_arg intrinsic does not work with `f32`"),
|
||||
Primitive::F128 => {
|
||||
bug!("the va_arg intrinsic does not work with `f128`")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => bug!("the va_arg intrinsic does not work with non-scalar types"),
|
||||
|
|
|
|||
|
|
@ -480,6 +480,9 @@ pub struct SanitizerOptions {
|
|||
pub sanitize_address: bool,
|
||||
pub sanitize_address_recover: bool,
|
||||
pub sanitize_cfi: bool,
|
||||
pub sanitize_dataflow: bool,
|
||||
pub sanitize_dataflow_abilist: *const *const c_char,
|
||||
pub sanitize_dataflow_abilist_len: size_t,
|
||||
pub sanitize_kcfi: bool,
|
||||
pub sanitize_memory: bool,
|
||||
pub sanitize_memory_recover: bool,
|
||||
|
|
@ -858,8 +861,10 @@ extern "C" {
|
|||
pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
|
||||
|
||||
// Operations on real types
|
||||
pub fn LLVMHalfTypeInContext(C: &Context) -> &Type;
|
||||
pub fn LLVMFloatTypeInContext(C: &Context) -> &Type;
|
||||
pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
|
||||
pub fn LLVMFP128TypeInContext(C: &Context) -> &Type;
|
||||
|
||||
// Operations on function types
|
||||
pub fn LLVMFunctionType<'a>(
|
||||
|
|
@ -1301,13 +1306,6 @@ extern "C" {
|
|||
NumIndices: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
pub fn LLVMBuildStructGEP2<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Pointer: &'a Value,
|
||||
Idx: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
|
||||
// Casts
|
||||
pub fn LLVMBuildTrunc<'a>(
|
||||
|
|
|
|||
|
|
@ -192,14 +192,11 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
|
|||
// to LLVM or the feature detection code will walk past the end of the feature
|
||||
// array, leading to crashes.
|
||||
//
|
||||
// To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def
|
||||
// where the * matches the architecture's name
|
||||
//
|
||||
// For targets not present in the above location, see llvm-project/llvm/lib/Target/{ARCH}/*.td
|
||||
// To find a list of LLVM's names, see llvm-project/llvm/lib/Target/{ARCH}/*.td
|
||||
// where `{ARCH}` is the architecture name. Look for instances of `SubtargetFeature`.
|
||||
//
|
||||
// Beware to not use the llvm github project for this, but check the git submodule
|
||||
// found in src/llvm-project
|
||||
// Check the current rustc fork of LLVM in the repo at https://github.com/rust-lang/llvm-project/.
|
||||
// The commit in use can be found via the `llvm-project` submodule in https://github.com/rust-lang/rust/tree/master/src
|
||||
// Though note that Rust can also be build with an external precompiled version of LLVM
|
||||
// which might lead to failures if the oldest tested / supported LLVM version
|
||||
// doesn't yet support the relevant intrinsics
|
||||
|
|
|
|||
|
|
@ -107,8 +107,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
pub(crate) fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type {
|
||||
match t {
|
||||
ty::FloatTy::F16 => self.type_f16(),
|
||||
ty::FloatTy::F32 => self.type_f32(),
|
||||
ty::FloatTy::F64 => self.type_f64(),
|
||||
ty::FloatTy::F128 => self.type_f128(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +158,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
self.isize_ty
|
||||
}
|
||||
|
||||
fn type_f16(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMHalfTypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFloatTypeInContext(self.llcx) }
|
||||
}
|
||||
|
|
@ -164,6 +170,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
fn type_f128(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFP128TypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
|
||||
}
|
||||
|
|
@ -195,7 +205,7 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
match self.type_kind(ty) {
|
||||
TypeKind::Array | TypeKind::Vector => unsafe { llvm::LLVMGetElementType(ty) },
|
||||
TypeKind::Pointer => bug!("element_type is not supported for opaque pointers"),
|
||||
other => bug!("element_type called on unsupported type {:?}", other),
|
||||
other => bug!("element_type called on unsupported type {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,11 +215,12 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
|
||||
fn float_width(&self, ty: &'ll Type) -> usize {
|
||||
match self.type_kind(ty) {
|
||||
TypeKind::Half => 16,
|
||||
TypeKind::Float => 32,
|
||||
TypeKind::Double => 64,
|
||||
TypeKind::X86_FP80 => 80,
|
||||
TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
|
||||
_ => bug!("llvm_float_width called on a non-float type"),
|
||||
other => bug!("llvm_float_width called on a non-float type {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,9 +261,6 @@ impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool {
|
||||
layout.is_llvm_scalar_pair()
|
||||
}
|
||||
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 {
|
||||
layout.llvm_field_index(self, index)
|
||||
}
|
||||
fn scalar_pair_element_backend_type(
|
||||
&self,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
|||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape};
|
||||
use rustc_target::abi::{Int, Pointer, F32, F64};
|
||||
use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
|
||||
use rustc_target::abi::{Scalar, Size, Variants};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
|
|
@ -174,7 +174,6 @@ pub trait LayoutLlvmExt<'tcx> {
|
|||
index: usize,
|
||||
immediate: bool,
|
||||
) -> &'a Type;
|
||||
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64;
|
||||
fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type>;
|
||||
}
|
||||
|
||||
|
|
@ -291,8 +290,10 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
|
||||
match scalar.primitive() {
|
||||
Int(i, _) => cx.type_from_integer(i),
|
||||
F16 => cx.type_f16(),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
F128 => cx.type_f128(),
|
||||
Pointer(address_space) => cx.type_ptr_ext(address_space),
|
||||
}
|
||||
}
|
||||
|
|
@ -324,42 +325,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
self.scalar_llvm_type_at(cx, scalar)
|
||||
}
|
||||
|
||||
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 {
|
||||
match self.abi {
|
||||
Abi::Scalar(_) | Abi::ScalarPair(..) => {
|
||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match self.fields {
|
||||
FieldsShape::Primitive | FieldsShape::Union(_) => {
|
||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
FieldsShape::Array { .. } => index as u64,
|
||||
|
||||
FieldsShape::Arbitrary { .. } => {
|
||||
let variant_index = match self.variants {
|
||||
Variants::Single { index } => Some(index),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// Look up llvm field if indexes do not match memory order due to padding. If
|
||||
// `field_remapping` is `None` no padding was used and the llvm field index
|
||||
// matches the memory index.
|
||||
match cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
|
||||
Some(TypeLowering { field_remapping: Some(ref remap), .. }) => {
|
||||
remap[index] as u64
|
||||
}
|
||||
Some(_) => self.fields.memory_index(index) as u64,
|
||||
None => {
|
||||
bug!("TyAndLayout::llvm_field_index({:?}): type info not found", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type> {
|
||||
debug_assert!(self.is_sized());
|
||||
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
|||
|
||||
let aligned_size = size.align_to(slot_size).bytes() as i32;
|
||||
let full_direct_size = bx.cx().const_i32(aligned_size);
|
||||
let next = bx.inbounds_gep(bx.type_i8(), addr, &[full_direct_size]);
|
||||
let next = bx.inbounds_ptradd(addr, full_direct_size);
|
||||
bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
|
||||
|
||||
if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big {
|
||||
let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
|
||||
let adjusted = bx.inbounds_gep(bx.type_i8(), addr, &[adjusted_size]);
|
||||
let adjusted = bx.inbounds_ptradd(addr, adjusted_size);
|
||||
(adjusted, addr_align)
|
||||
} else {
|
||||
(addr, addr_align)
|
||||
|
|
@ -89,11 +89,31 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
list: OperandRef<'tcx, &'ll Value>,
|
||||
target_ty: Ty<'tcx>,
|
||||
) -> &'ll Value {
|
||||
let dl = bx.cx.data_layout();
|
||||
|
||||
// Implementation of the AAPCS64 calling convention for va_args see
|
||||
// https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
|
||||
//
|
||||
// typedef struct va_list {
|
||||
// void * stack; // next stack param
|
||||
// void * gr_top; // end of GP arg reg save area
|
||||
// void * vr_top; // end of FP/SIMD arg reg save area
|
||||
// int gr_offs; // offset from gr_top to next GP register arg
|
||||
// int vr_offs; // offset from vr_top to next FP/SIMD register arg
|
||||
// } va_list;
|
||||
let va_list_addr = list.immediate();
|
||||
let va_list_layout = list.deref(bx.cx).layout;
|
||||
let va_list_ty = va_list_layout.llvm_type(bx);
|
||||
|
||||
// There is no padding between fields since `void*` is size=8 align=8, `int` is size=4 align=4.
|
||||
// See https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
|
||||
// Table 1, Byte size and byte alignment of fundamental data types
|
||||
// Table 3, Mapping of C & C++ built-in data types
|
||||
let ptr_offset = 8;
|
||||
let i32_offset = 4;
|
||||
let gr_top = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(ptr_offset));
|
||||
let vr_top = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * ptr_offset));
|
||||
let gr_offs = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(3 * ptr_offset));
|
||||
let vr_offs = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(3 * ptr_offset + i32_offset));
|
||||
|
||||
let layout = bx.cx.layout_of(target_ty);
|
||||
|
||||
let maybe_reg = bx.append_sibling_block("va_arg.maybe_reg");
|
||||
|
|
@ -104,16 +124,12 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
let offset_align = Align::from_bytes(4).unwrap();
|
||||
|
||||
let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
|
||||
let (reg_off, reg_top_index, slot_size) = if gr_type {
|
||||
let gr_offs =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 3));
|
||||
let (reg_off, reg_top, slot_size) = if gr_type {
|
||||
let nreg = (layout.size.bytes() + 7) / 8;
|
||||
(gr_offs, va_list_layout.llvm_field_index(bx.cx, 1), nreg * 8)
|
||||
(gr_offs, gr_top, nreg * 8)
|
||||
} else {
|
||||
let vr_off =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 4));
|
||||
let nreg = (layout.size.bytes() + 15) / 16;
|
||||
(vr_off, va_list_layout.llvm_field_index(bx.cx, 2), nreg * 16)
|
||||
(vr_offs, vr_top, nreg * 16)
|
||||
};
|
||||
|
||||
// if the offset >= 0 then the value will be on the stack
|
||||
|
|
@ -141,15 +157,14 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
|
||||
bx.switch_to_block(in_reg);
|
||||
let top_type = bx.type_ptr();
|
||||
let top = bx.struct_gep(va_list_ty, va_list_addr, reg_top_index);
|
||||
let top = bx.load(top_type, top, bx.tcx().data_layout.pointer_align.abi);
|
||||
let top = bx.load(top_type, reg_top, dl.pointer_align.abi);
|
||||
|
||||
// reg_value = *(@top + reg_off_v);
|
||||
let mut reg_addr = bx.gep(bx.type_i8(), top, &[reg_off_v]);
|
||||
let mut reg_addr = bx.ptradd(top, reg_off_v);
|
||||
if bx.tcx().sess.target.endian == Endian::Big && layout.size.bytes() != slot_size {
|
||||
// On big-endian systems the value is right-aligned in its slot.
|
||||
let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32);
|
||||
reg_addr = bx.gep(bx.type_i8(), reg_addr, &[offset]);
|
||||
reg_addr = bx.ptradd(reg_addr, offset);
|
||||
}
|
||||
let reg_type = layout.llvm_type(bx);
|
||||
let reg_value = bx.load(reg_type, reg_addr, layout.align.abi);
|
||||
|
|
@ -173,11 +188,29 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
list: OperandRef<'tcx, &'ll Value>,
|
||||
target_ty: Ty<'tcx>,
|
||||
) -> &'ll Value {
|
||||
let dl = bx.cx.data_layout();
|
||||
|
||||
// Implementation of the s390x ELF ABI calling convention for va_args see
|
||||
// https://github.com/IBM/s390x-abi (chapter 1.2.4)
|
||||
//
|
||||
// typedef struct __va_list_tag {
|
||||
// long __gpr;
|
||||
// long __fpr;
|
||||
// void *__overflow_arg_area;
|
||||
// void *__reg_save_area;
|
||||
// } va_list[1];
|
||||
let va_list_addr = list.immediate();
|
||||
let va_list_layout = list.deref(bx.cx).layout;
|
||||
let va_list_ty = va_list_layout.llvm_type(bx);
|
||||
|
||||
// There is no padding between fields since `long` and `void*` both have size=8 align=8.
|
||||
// https://github.com/IBM/s390x-abi (Table 1.1.: Scalar types)
|
||||
let i64_offset = 8;
|
||||
let ptr_offset = 8;
|
||||
let gpr = va_list_addr;
|
||||
let fpr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(i64_offset));
|
||||
let overflow_arg_area = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * i64_offset));
|
||||
let reg_save_area =
|
||||
bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * i64_offset + ptr_offset));
|
||||
|
||||
let layout = bx.cx.layout_of(target_ty);
|
||||
|
||||
let in_reg = bx.append_sibling_block("va_arg.in_reg");
|
||||
|
|
@ -192,15 +225,10 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
let padding = padded_size - unpadded_size;
|
||||
|
||||
let gpr_type = indirect || !layout.is_single_fp_element(bx.cx);
|
||||
let (max_regs, reg_count_field, reg_save_index, reg_padding) =
|
||||
if gpr_type { (5, 0, 2, padding) } else { (4, 1, 16, 0) };
|
||||
let (max_regs, reg_count, reg_save_index, reg_padding) =
|
||||
if gpr_type { (5, gpr, 2, padding) } else { (4, fpr, 16, 0) };
|
||||
|
||||
// Check whether the value was passed in a register or in memory.
|
||||
let reg_count = bx.struct_gep(
|
||||
va_list_ty,
|
||||
va_list_addr,
|
||||
va_list_layout.llvm_field_index(bx.cx, reg_count_field),
|
||||
);
|
||||
let reg_count_v = bx.load(bx.type_i64(), reg_count, Align::from_bytes(8).unwrap());
|
||||
let use_regs = bx.icmp(IntPredicate::IntULT, reg_count_v, bx.const_u64(max_regs));
|
||||
bx.cond_br(use_regs, in_reg, in_mem);
|
||||
|
|
@ -209,12 +237,10 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
bx.switch_to_block(in_reg);
|
||||
|
||||
// Work out the address of the value in the register save area.
|
||||
let reg_ptr =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 3));
|
||||
let reg_ptr_v = bx.load(bx.type_ptr(), reg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, dl.pointer_align.abi);
|
||||
let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8));
|
||||
let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding));
|
||||
let reg_addr = bx.gep(bx.type_i8(), reg_ptr_v, &[reg_off]);
|
||||
let reg_addr = bx.ptradd(reg_ptr_v, reg_off);
|
||||
|
||||
// Update the register count.
|
||||
let new_reg_count_v = bx.add(reg_count_v, bx.const_u64(1));
|
||||
|
|
@ -225,27 +251,23 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
bx.switch_to_block(in_mem);
|
||||
|
||||
// Work out the address of the value in the argument overflow area.
|
||||
let arg_ptr =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 2));
|
||||
let arg_ptr_v = bx.load(bx.type_ptr(), arg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let arg_ptr_v =
|
||||
bx.load(bx.type_ptr(), overflow_arg_area, bx.tcx().data_layout.pointer_align.abi);
|
||||
let arg_off = bx.const_u64(padding);
|
||||
let mem_addr = bx.gep(bx.type_i8(), arg_ptr_v, &[arg_off]);
|
||||
let mem_addr = bx.ptradd(arg_ptr_v, arg_off);
|
||||
|
||||
// Update the argument overflow area pointer.
|
||||
let arg_size = bx.cx().const_u64(padded_size);
|
||||
let new_arg_ptr_v = bx.inbounds_gep(bx.type_i8(), arg_ptr_v, &[arg_size]);
|
||||
bx.store(new_arg_ptr_v, arg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let new_arg_ptr_v = bx.inbounds_ptradd(arg_ptr_v, arg_size);
|
||||
bx.store(new_arg_ptr_v, overflow_arg_area, dl.pointer_align.abi);
|
||||
bx.br(end);
|
||||
|
||||
// Return the appropriate result.
|
||||
bx.switch_to_block(end);
|
||||
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
|
||||
let val_type = layout.llvm_type(bx);
|
||||
let val_addr = if indirect {
|
||||
bx.load(bx.cx.type_ptr(), val_addr, bx.tcx().data_layout.pointer_align.abi)
|
||||
} else {
|
||||
val_addr
|
||||
};
|
||||
let val_addr =
|
||||
if indirect { bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) } else { val_addr };
|
||||
bx.load(val_type, val_addr, layout.align.abi)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ tempfile = "3.2"
|
|||
thin-vec = "0.2.12"
|
||||
thorin-dwp = "0.7"
|
||||
tracing = "0.1"
|
||||
wasm-encoder = "0.200.0"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
|||
/// Scan for a `cfg="foo"` attribute and check whether we have a
|
||||
/// cfg flag called `foo`.
|
||||
fn check_config(&self, attr: &ast::Attribute) -> bool {
|
||||
let config = &self.tcx.sess.parse_sess.config;
|
||||
let config = &self.tcx.sess.psess.config;
|
||||
let value = self.field(attr, sym::cfg);
|
||||
debug!("check_config(config={:?}, value={:?})", config, value);
|
||||
if config.iter().any(|&(name, _)| name == value) {
|
||||
|
|
|
|||
|
|
@ -315,8 +315,11 @@ fn link_rlib<'a>(
|
|||
|
||||
let trailing_metadata = match flavor {
|
||||
RlibFlavor::Normal => {
|
||||
let (metadata, metadata_position) =
|
||||
create_wrapper_file(sess, b".rmeta".to_vec(), codegen_results.metadata.raw_data());
|
||||
let (metadata, metadata_position) = create_wrapper_file(
|
||||
sess,
|
||||
".rmeta".to_string(),
|
||||
codegen_results.metadata.raw_data(),
|
||||
);
|
||||
let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
|
||||
match metadata_position {
|
||||
MetadataPosition::First => {
|
||||
|
|
@ -384,7 +387,7 @@ fn link_rlib<'a>(
|
|||
let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess);
|
||||
let src = read(path)
|
||||
.map_err(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }))?;
|
||||
let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
|
||||
let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src);
|
||||
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
|
||||
packed_bundled_libs.push(wrapper_file);
|
||||
} else {
|
||||
|
|
@ -1218,6 +1221,9 @@ fn add_sanitizer_libraries(
|
|||
if sanitizer.contains(SanitizerSet::ADDRESS) {
|
||||
link_sanitizer_runtime(sess, flavor, linker, "asan");
|
||||
}
|
||||
if sanitizer.contains(SanitizerSet::DATAFLOW) {
|
||||
link_sanitizer_runtime(sess, flavor, linker, "dfsan");
|
||||
}
|
||||
if sanitizer.contains(SanitizerSet::LEAK) {
|
||||
link_sanitizer_runtime(sess, flavor, linker, "lsan");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1631,7 +1631,9 @@ impl<'a> Linker for AixLinker<'a> {
|
|||
|
||||
fn optimize(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
fn pgo_gen(&mut self) {
|
||||
self.cmd.arg("-bdbg:namedsects:ss");
|
||||
}
|
||||
|
||||
fn control_flow_guard(&mut self) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Reading of the rustc metadata for rlibs and dylibs
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
|
@ -15,7 +16,6 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
|
|||
use rustc_metadata::creader::MetadataLoader;
|
||||
use rustc_metadata::fs::METADATA_FILENAME;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_serialize::leb128;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::abi::Endian;
|
||||
|
|
@ -434,12 +434,15 @@ pub enum MetadataPosition {
|
|||
/// automatically removed from the final output.
|
||||
pub fn create_wrapper_file(
|
||||
sess: &Session,
|
||||
section_name: Vec<u8>,
|
||||
section_name: String,
|
||||
data: &[u8],
|
||||
) -> (Vec<u8>, MetadataPosition) {
|
||||
let Some(mut file) = create_object_file(sess) else {
|
||||
if sess.target.is_like_wasm {
|
||||
return (create_metadata_file_for_wasm(data, §ion_name), MetadataPosition::First);
|
||||
return (
|
||||
create_metadata_file_for_wasm(sess, data, §ion_name),
|
||||
MetadataPosition::First,
|
||||
);
|
||||
}
|
||||
|
||||
// Targets using this branch don't have support implemented here yet or
|
||||
|
|
@ -452,7 +455,7 @@ pub fn create_wrapper_file(
|
|||
} else {
|
||||
file.add_section(
|
||||
file.segment_name(StandardSegment::Debug).to_vec(),
|
||||
section_name,
|
||||
section_name.into_bytes(),
|
||||
SectionKind::Debug,
|
||||
)
|
||||
};
|
||||
|
|
@ -524,7 +527,7 @@ pub fn create_compressed_metadata_file(
|
|||
|
||||
let Some(mut file) = create_object_file(sess) else {
|
||||
if sess.target.is_like_wasm {
|
||||
return create_metadata_file_for_wasm(&packed_metadata, b".rustc");
|
||||
return create_metadata_file_for_wasm(sess, &packed_metadata, ".rustc");
|
||||
}
|
||||
return packed_metadata.to_vec();
|
||||
};
|
||||
|
|
@ -624,51 +627,41 @@ pub fn create_compressed_metadata_file_for_xcoff(
|
|||
/// `data`.
|
||||
///
|
||||
/// NB: the `object` crate does not yet have support for writing the wasm
|
||||
/// object file format. The format is simple enough that for now an extra crate
|
||||
/// from crates.io (such as `wasm-encoder`). The file format is:
|
||||
/// object file format. In lieu of that the `wasm-encoder` crate is used to
|
||||
/// build a wasm file by hand.
|
||||
///
|
||||
/// * 4-byte header "\0asm"
|
||||
/// * 4-byte version number - 1u32 in little-endian format
|
||||
/// * concatenated sections, which for this object is always "custom sections"
|
||||
///
|
||||
/// Custom sections are then defined by:
|
||||
/// * 1-byte section identifier - 0 for a custom section
|
||||
/// * leb-encoded section length (size of the contents beneath this bullet)
|
||||
/// * leb-encoded custom section name length
|
||||
/// * custom section name
|
||||
/// * section contents
|
||||
///
|
||||
/// One custom section, `linking`, is added here in accordance with
|
||||
/// The wasm object file format is defined at
|
||||
/// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md>
|
||||
/// which is required to inform LLD that this is an object file but it should
|
||||
/// otherwise basically ignore it if it otherwise looks at it. The linking
|
||||
/// section currently is defined by a single version byte (2) and then further
|
||||
/// sections, but we have no more sections, so it's just the byte "2".
|
||||
/// and mainly consists of a `linking` custom section. In this case the custom
|
||||
/// section there is empty except for a version marker indicating what format
|
||||
/// it's in.
|
||||
///
|
||||
/// The next custom section is the one we're interested in.
|
||||
pub fn create_metadata_file_for_wasm(data: &[u8], section_name: &[u8]) -> Vec<u8> {
|
||||
let mut bytes = b"\0asm\x01\0\0\0".to_vec();
|
||||
/// The main purpose of this is to contain a custom section with `section_name`,
|
||||
/// which is then appended after `linking`.
|
||||
///
|
||||
/// As a further detail the object needs to have a 64-bit memory if `wasm64` is
|
||||
/// the target or otherwise it's interpreted as a 32-bit object which is
|
||||
/// incompatible with 64-bit ones.
|
||||
pub fn create_metadata_file_for_wasm(sess: &Session, data: &[u8], section_name: &str) -> Vec<u8> {
|
||||
assert!(sess.target.is_like_wasm);
|
||||
let mut module = wasm_encoder::Module::new();
|
||||
let mut imports = wasm_encoder::ImportSection::new();
|
||||
|
||||
let mut append_custom_section = |section_name: &[u8], data: &[u8]| {
|
||||
let mut section_name_len = [0; leb128::max_leb128_len::<usize>()];
|
||||
let off = leb128::write_usize_leb128(&mut section_name_len, section_name.len());
|
||||
let section_name_len = §ion_name_len[..off];
|
||||
|
||||
let mut section_len = [0; leb128::max_leb128_len::<usize>()];
|
||||
let off = leb128::write_usize_leb128(
|
||||
&mut section_len,
|
||||
data.len() + section_name_len.len() + section_name.len(),
|
||||
if sess.target.pointer_width == 64 {
|
||||
imports.import(
|
||||
"env",
|
||||
"__linear_memory",
|
||||
wasm_encoder::MemoryType { minimum: 0, maximum: None, memory64: true, shared: false },
|
||||
);
|
||||
let section_len = §ion_len[..off];
|
||||
}
|
||||
|
||||
bytes.push(0u8);
|
||||
bytes.extend_from_slice(section_len);
|
||||
bytes.extend_from_slice(section_name_len);
|
||||
bytes.extend_from_slice(section_name);
|
||||
bytes.extend_from_slice(data);
|
||||
};
|
||||
|
||||
append_custom_section(b"linking", &[2]);
|
||||
append_custom_section(section_name, data);
|
||||
bytes
|
||||
if imports.len() > 0 {
|
||||
module.section(&imports);
|
||||
}
|
||||
module.section(&wasm_encoder::CustomSection {
|
||||
name: "linking".into(),
|
||||
data: Cow::Borrowed(&[2]),
|
||||
});
|
||||
module.section(&wasm_encoder::CustomSection { name: section_name.into(), data: data.into() });
|
||||
module.finish()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
|||
return library.kind.is_statically_included().then_some(def_id);
|
||||
}
|
||||
|
||||
if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Only consider nodes that actually have exported symbols.
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Fn | DefKind::Static(_) => {}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc;
|
|||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::{
|
||||
Diag, DiagArgMap, DiagCtxt, DiagnosticMessage, ErrCode, FatalError, FluentBundle, Level,
|
||||
MultiSpan, Style,
|
||||
Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan,
|
||||
Style,
|
||||
};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
|
|
@ -95,6 +95,7 @@ pub struct ModuleConfig {
|
|||
|
||||
pub sanitizer: SanitizerSet,
|
||||
pub sanitizer_recover: SanitizerSet,
|
||||
pub sanitizer_dataflow_abilist: Vec<String>,
|
||||
pub sanitizer_memory_track_origins: usize,
|
||||
|
||||
// Flags indicating which outputs to produce.
|
||||
|
|
@ -197,6 +198,10 @@ impl ModuleConfig {
|
|||
),
|
||||
|
||||
sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
|
||||
sanitizer_dataflow_abilist: if_regular!(
|
||||
sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
|
||||
Vec::new()
|
||||
),
|
||||
sanitizer_recover: if_regular!(
|
||||
sess.opts.unstable_opts.sanitizer_recover,
|
||||
SanitizerSet::empty()
|
||||
|
|
@ -999,9 +1004,9 @@ pub(crate) enum Message<B: WriteBackendMethods> {
|
|||
/// process another codegen unit.
|
||||
pub struct CguMessage;
|
||||
|
||||
// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which
|
||||
// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which
|
||||
// can be used to send diagnostics from codegen threads to the main thread.
|
||||
// It's missing the following fields from `rustc_errors::Diagnostic`.
|
||||
// It's missing the following fields from `rustc_errors::DiagInner`.
|
||||
// - `span`: it doesn't impl `Send`.
|
||||
// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
|
||||
// diagnostics.
|
||||
|
|
@ -1010,18 +1015,18 @@ pub struct CguMessage;
|
|||
// - `emitted_at`: not used for codegen diagnostics.
|
||||
struct Diagnostic {
|
||||
level: Level,
|
||||
messages: Vec<(DiagnosticMessage, Style)>,
|
||||
messages: Vec<(DiagMessage, Style)>,
|
||||
code: Option<ErrCode>,
|
||||
children: Vec<Subdiagnostic>,
|
||||
args: DiagArgMap,
|
||||
}
|
||||
|
||||
// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's
|
||||
// missing the following fields from `rustc_errors::SubDiagnostic`.
|
||||
// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's
|
||||
// missing the following fields from `rustc_errors::Subdiag`.
|
||||
// - `span`: it doesn't impl `Send`.
|
||||
pub struct Subdiagnostic {
|
||||
level: Level,
|
||||
messages: Vec<(DiagnosticMessage, Style)>,
|
||||
messages: Vec<(DiagMessage, Style)>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
.map_err(|msg| {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
attr.span,
|
||||
literal.span,
|
||||
E0589,
|
||||
"invalid `repr(align)` attribute: {}",
|
||||
msg
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ use crate::MemFlags;
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason};
|
||||
use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason};
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::{source_map::Spanned, sym, Span, Symbol};
|
||||
use rustc_span::{source_map::Spanned, sym, Span};
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
|
||||
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
|
@ -680,7 +680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&mut self,
|
||||
helper: &TerminatorCodegenHelper<'tcx>,
|
||||
bx: &mut Bx,
|
||||
intrinsic: Option<Symbol>,
|
||||
intrinsic: Option<ty::IntrinsicDef>,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
source_info: mir::SourceInfo,
|
||||
target: Option<mir::BasicBlock>,
|
||||
|
|
@ -690,7 +690,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// Emit a panic or a no-op for `assert_*` intrinsics.
|
||||
// These are intrinsics that compile to panics so that we can get a message
|
||||
// which mentions the offending type, even from a const context.
|
||||
let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
|
||||
let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
|
||||
if let Some(requirement) = panic_intrinsic {
|
||||
let ty = instance.unwrap().args.type_at(0);
|
||||
|
||||
|
|
@ -826,14 +826,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// The arguments we'll be passing. Plus one to account for outptr, if used.
|
||||
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
|
||||
|
||||
if intrinsic == Some(sym::caller_location) {
|
||||
if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
|
||||
return if let Some(target) = target {
|
||||
let location =
|
||||
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
let ret_dest =
|
||||
self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, true, true);
|
||||
let ret_dest = self.make_return_dest(
|
||||
bx,
|
||||
destination,
|
||||
&fn_abi.ret,
|
||||
&mut llargs,
|
||||
intrinsic,
|
||||
Some(target),
|
||||
);
|
||||
assert_eq!(llargs, []);
|
||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||
location.val.store(bx, tmp);
|
||||
|
|
@ -846,7 +852,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
let instance = match intrinsic {
|
||||
None | Some(sym::drop_in_place) => instance,
|
||||
None => instance,
|
||||
Some(intrinsic) => {
|
||||
let mut llargs = Vec::with_capacity(1);
|
||||
let ret_dest = self.make_return_dest(
|
||||
|
|
@ -854,8 +860,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
destination,
|
||||
&fn_abi.ret,
|
||||
&mut llargs,
|
||||
true,
|
||||
target.is_some(),
|
||||
Some(intrinsic),
|
||||
target,
|
||||
);
|
||||
let dest = match ret_dest {
|
||||
_ if fn_abi.ret.is_indirect() => llargs[0],
|
||||
|
|
@ -873,7 +879,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// The indices passed to simd_shuffle in the
|
||||
// third argument must be constant. This is
|
||||
// checked by the type-checker.
|
||||
if i == 2 && intrinsic == sym::simd_shuffle {
|
||||
if i == 2 && intrinsic.name == sym::simd_shuffle {
|
||||
if let mir::Operand::Constant(constant) = &arg.node {
|
||||
let (llval, ty) = self.simd_shuffle_indices(bx, constant);
|
||||
return OperandRef {
|
||||
|
|
@ -903,14 +909,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
MergingSucc::False
|
||||
};
|
||||
}
|
||||
Err(instance) => Some(instance),
|
||||
Err(instance) => {
|
||||
if intrinsic.must_be_overridden {
|
||||
span_bug!(
|
||||
span,
|
||||
"intrinsic {} must be overridden by codegen backend, but isn't",
|
||||
intrinsic.name,
|
||||
);
|
||||
}
|
||||
Some(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut llargs = Vec::with_capacity(arg_count);
|
||||
let destination = target.as_ref().map(|&target| {
|
||||
(self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, false, true), target)
|
||||
(
|
||||
self.make_return_dest(
|
||||
bx,
|
||||
destination,
|
||||
&fn_abi.ret,
|
||||
&mut llargs,
|
||||
None,
|
||||
Some(target),
|
||||
),
|
||||
target,
|
||||
)
|
||||
});
|
||||
|
||||
// Split the rust-call tupled arguments off.
|
||||
|
|
@ -1643,10 +1668,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dest: mir::Place<'tcx>,
|
||||
fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
|
||||
llargs: &mut Vec<Bx::Value>,
|
||||
is_intrinsic: bool,
|
||||
has_target: bool,
|
||||
intrinsic: Option<ty::IntrinsicDef>,
|
||||
target: Option<BasicBlock>,
|
||||
) -> ReturnDest<'tcx, Bx::Value> {
|
||||
if !has_target {
|
||||
if target.is_none() {
|
||||
return ReturnDest::Nothing;
|
||||
}
|
||||
// If the return is ignored, we can just return a do-nothing `ReturnDest`.
|
||||
|
|
@ -1667,7 +1692,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
tmp.storage_live(bx);
|
||||
llargs.push(tmp.llval);
|
||||
ReturnDest::IndirectOperand(tmp, index)
|
||||
} else if is_intrinsic {
|
||||
} else if intrinsic.is_some() {
|
||||
// Currently, intrinsics always need a location to store
|
||||
// the result, so we create a temporary `alloca` for the
|
||||
// result.
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
|
||||
pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
|
||||
if self.layout.ty.is_box() {
|
||||
// Derefer should have removed all Box derefs
|
||||
bug!("dereferencing {:?} in codegen", self.layout.ty);
|
||||
}
|
||||
|
||||
|
|
@ -437,8 +438,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
let align = dest.align;
|
||||
bx.store_with_flags(val, dest.llval, align, flags);
|
||||
|
||||
let llptr =
|
||||
bx.inbounds_gep(bx.type_i8(), dest.llval, &[bx.const_usize(b_offset.bytes())]);
|
||||
let llptr = bx.inbounds_ptradd(dest.llval, bx.const_usize(b_offset.bytes()));
|
||||
let val = bx.from_immediate(b);
|
||||
let align = dest.align.restrict_for_offset(b_offset);
|
||||
bx.store_with_flags(val, llptr, align, flags);
|
||||
|
|
@ -476,7 +476,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
let address = bx.ptrtoint(alloca, bx.type_isize());
|
||||
let neg_address = bx.neg(address);
|
||||
let offset = bx.and(neg_address, align_minus_1);
|
||||
let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]);
|
||||
let dst = bx.inbounds_ptradd(alloca, offset);
|
||||
bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
|
||||
|
||||
// Store the allocated region and the extra to the indirect place.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_middle::mir;
|
|||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape, Int, Pointer, TagEncoding};
|
||||
use rustc_target::abi::{Align, FieldsShape, Int, Pointer, TagEncoding};
|
||||
use rustc_target::abi::{VariantIdx, Variants};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
@ -102,34 +102,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
// `simple` is called when we don't need to adjust the offset to
|
||||
// the dynamic alignment of the field.
|
||||
let mut simple = || {
|
||||
let llval = match self.layout.abi {
|
||||
_ if offset.bytes() == 0 => {
|
||||
// Unions and newtypes only use an offset of 0.
|
||||
// Also handles the first field of Scalar, ScalarPair, and Vector layouts.
|
||||
self.llval
|
||||
}
|
||||
Abi::ScalarPair(..) => {
|
||||
// FIXME(nikic): Generate this for all ABIs.
|
||||
bx.inbounds_gep(bx.type_i8(), self.llval, &[bx.const_usize(offset.bytes())])
|
||||
}
|
||||
Abi::Scalar(_) | Abi::Vector { .. } if field.is_zst() => {
|
||||
// ZST fields (even some that require alignment) are not included in Scalar,
|
||||
// ScalarPair, and Vector layouts, so manually offset the pointer.
|
||||
bx.gep(bx.cx().type_i8(), self.llval, &[bx.const_usize(offset.bytes())])
|
||||
}
|
||||
Abi::Scalar(_) => {
|
||||
// All fields of Scalar layouts must have been handled by this point.
|
||||
// Vector layouts have additional fields for each element of the vector, so don't panic in that case.
|
||||
bug!(
|
||||
"offset of non-ZST field `{:?}` does not match layout `{:#?}`",
|
||||
field,
|
||||
self.layout
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let ty = bx.backend_type(self.layout);
|
||||
bx.struct_gep(ty, self.llval, bx.cx().backend_field_index(self.layout, ix))
|
||||
}
|
||||
let llval = if offset.bytes() == 0 {
|
||||
self.llval
|
||||
} else if field.is_zst() {
|
||||
// FIXME(erikdesjardins): it should be fine to use inbounds for ZSTs too;
|
||||
// keeping this logic for now to preserve previous behavior.
|
||||
bx.ptradd(self.llval, bx.const_usize(offset.bytes()))
|
||||
} else {
|
||||
bx.inbounds_ptradd(self.llval, bx.const_usize(offset.bytes()))
|
||||
};
|
||||
PlaceRef {
|
||||
llval,
|
||||
|
|
@ -188,7 +168,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
debug!("struct_field_ptr: DST field offset: {:?}", offset);
|
||||
|
||||
// Adjust pointer.
|
||||
let ptr = bx.gep(bx.cx().type_i8(), self.llval, &[offset]);
|
||||
// FIXME(erikdesjardins): should be able to use inbounds here too.
|
||||
let ptr = bx.ptradd(self.llval, offset);
|
||||
|
||||
PlaceRef { llval: ptr, llextra: self.llextra, layout: field, align: effective_field_align }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,8 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
if let OperandValue::Immediate(v) = cg_elem.val {
|
||||
let zero = bx.const_usize(0);
|
||||
let start = dest.project_index(bx, zero).llval;
|
||||
let start = dest.llval;
|
||||
let size = bx.const_usize(dest.layout.size.bytes());
|
||||
|
||||
// Use llvm.memset.p0i8.* to initialize all zero arrays
|
||||
|
|
@ -303,15 +302,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
|
||||
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
|
||||
(Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty),
|
||||
(Int(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => {
|
||||
bx.bitcast(imm, to_backend_ty)
|
||||
}
|
||||
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
|
||||
(Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty),
|
||||
(Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
|
||||
(F32 | F64, Pointer(..)) => {
|
||||
(F16 | F32 | F64 | F128, Pointer(..)) => {
|
||||
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
||||
bx.inttoptr(int_imm, to_backend_ty)
|
||||
}
|
||||
(Pointer(..), F32 | F64) => {
|
||||
(Pointer(..), F16 | F32 | F64 | F128) => {
|
||||
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
|
||||
bx.bitcast(int_imm, to_backend_ty)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,12 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
ptr: Self::Value,
|
||||
indices: &[Self::Value],
|
||||
) -> Self::Value;
|
||||
fn struct_gep(&mut self, ty: Self::Type, ptr: Self::Value, idx: u64) -> Self::Value;
|
||||
fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
|
||||
self.gep(self.cx().type_i8(), ptr, &[offset])
|
||||
}
|
||||
fn inbounds_ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
|
||||
self.inbounds_gep(self.cx().type_i8(), ptr, &[offset])
|
||||
}
|
||||
|
||||
fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
||||
fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
|||
fn type_i128(&self) -> Self::Type;
|
||||
fn type_isize(&self) -> Self::Type;
|
||||
|
||||
fn type_f16(&self) -> Self::Type;
|
||||
fn type_f32(&self) -> Self::Type;
|
||||
fn type_f64(&self) -> Self::Type;
|
||||
fn type_f128(&self) -> Self::Type;
|
||||
|
||||
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
|
|
@ -111,7 +113,6 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
|
|||
fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
|
||||
fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool;
|
||||
fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool;
|
||||
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64;
|
||||
fn scalar_pair_element_backend_type(
|
||||
&self,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
|
|
|
|||
|
|
@ -453,7 +453,6 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
|
|||
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
|
||||
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
|
||||
const_eval_validation_mutable_ref_in_const_or_static = {$front_matter}: encountered mutable reference in a `const` or `static`
|
||||
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
|
||||
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
|
||||
const_eval_validation_null_box = {$front_matter}: encountered a null box
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_errors::{
|
||||
DiagArgName, DiagArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg,
|
||||
};
|
||||
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, IntoDiagnostic, IntoDiagnosticArg};
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
|
|
@ -25,7 +23,7 @@ pub enum ConstEvalErrKind {
|
|||
}
|
||||
|
||||
impl MachineStopType for ConstEvalErrKind {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
use ConstEvalErrKind::*;
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_errors::{
|
||||
codes::*, Diag, DiagArgValue, DiagCtxt, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic,
|
||||
Level,
|
||||
codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, EmissionGuarantee, IntoDiagnostic, Level,
|
||||
};
|
||||
use rustc_hir::ConstContext;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
|
|
@ -424,7 +423,7 @@ pub struct UndefinedBehavior {
|
|||
|
||||
pub trait ReportErrorExt {
|
||||
/// Returns the diagnostic message for this error.
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage;
|
||||
fn diagnostic_message(&self) -> DiagMessage;
|
||||
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
|
||||
|
||||
fn debug(self) -> String
|
||||
|
|
@ -433,7 +432,7 @@ pub trait ReportErrorExt {
|
|||
{
|
||||
ty::tls::with(move |tcx| {
|
||||
let dcx = tcx.dcx();
|
||||
let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
|
||||
let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into()));
|
||||
let message = self.diagnostic_message();
|
||||
self.add_args(&mut diag);
|
||||
let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
|
||||
|
|
@ -457,7 +456,7 @@ fn bad_pointer_message(msg: CheckInAllocMsg, dcx: &DiagCtxt) -> String {
|
|||
}
|
||||
|
||||
impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
use UndefinedBehaviorInfo::*;
|
||||
match self {
|
||||
|
|
@ -595,7 +594,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||
}
|
||||
|
||||
impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
use rustc_middle::mir::interpret::ValidationErrorKind::*;
|
||||
match self.kind {
|
||||
|
|
@ -613,7 +612,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
PartialPointer => const_eval_validation_partial_pointer,
|
||||
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
|
||||
ConstRefToExtern => const_eval_validation_const_ref_to_extern,
|
||||
MutableRefInConstOrStatic => const_eval_validation_mutable_ref_in_const_or_static,
|
||||
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
|
||||
NullFnPtr => const_eval_validation_null_fn_ptr,
|
||||
NeverVal => const_eval_validation_never_val,
|
||||
|
|
@ -767,7 +765,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
}
|
||||
NullPtr { .. }
|
||||
| PtrToStatic { .. }
|
||||
| MutableRefInConstOrStatic
|
||||
| ConstRefToMutable
|
||||
| ConstRefToExtern
|
||||
| MutableRefToImmutable
|
||||
|
|
@ -785,7 +782,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
}
|
||||
|
||||
impl ReportErrorExt for UnsupportedOpInfo {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
match self {
|
||||
UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
|
||||
|
|
@ -821,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
|||
}
|
||||
|
||||
impl<'tcx> ReportErrorExt for InterpError<'tcx> {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
match self {
|
||||
InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(),
|
||||
InterpError::Unsupported(e) => e.diagnostic_message(),
|
||||
|
|
@ -844,7 +841,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
match self {
|
||||
InvalidProgramInfo::TooGeneric => const_eval_too_generic,
|
||||
|
|
@ -879,7 +876,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
|
|||
}
|
||||
|
||||
impl ReportErrorExt for ResourceExhaustionInfo {
|
||||
fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
fn diagnostic_message(&self) -> DiagMessage {
|
||||
use crate::fluent_generated::*;
|
||||
match self {
|
||||
ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
|
||||
|
|
|
|||
|
|
@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||
use rustc_type_ir::TyKind::*;
|
||||
|
||||
let val = match src.layout.ty.kind() {
|
||||
// Floating point
|
||||
Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
|
||||
Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
|
||||
_ => {
|
||||
bug!("Can't cast 'Float' type into {}", cast_to.ty);
|
||||
}
|
||||
let Float(fty) = src.layout.ty.kind() else {
|
||||
bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty)
|
||||
};
|
||||
let val = match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
|
||||
FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
};
|
||||
Ok(ImmTy::from_scalar(val, cast_to))
|
||||
}
|
||||
|
|
@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
|
||||
|
||||
Ok(match *cast_ty.kind() {
|
||||
// int -> int
|
||||
Int(_) | Uint(_) => {
|
||||
let size = match *cast_ty.kind() {
|
||||
Int(t) => Integer::from_int_ty(self, t).size(),
|
||||
|
|
@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Scalar::from_uint(v, size)
|
||||
}
|
||||
|
||||
Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
|
||||
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
|
||||
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
|
||||
Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value),
|
||||
|
||||
Char => {
|
||||
// `u8` to `char` cast
|
||||
Scalar::from_u32(u8::try_from(v).unwrap().into())
|
||||
// signed int -> float
|
||||
Float(fty) if signed => {
|
||||
let v = v as i128;
|
||||
match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value),
|
||||
FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
}
|
||||
}
|
||||
// unsigned int -> float
|
||||
Float(fty) => match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value),
|
||||
FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
},
|
||||
|
||||
// u8 -> char
|
||||
Char => Scalar::from_u32(u8::try_from(v).unwrap().into()),
|
||||
|
||||
// Casts to bool are not permitted by rustc, no need to handle them here.
|
||||
_ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty),
|
||||
|
|
@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let v = f.to_i128(size.bits_usize()).value;
|
||||
Scalar::from_int(v, size)
|
||||
}
|
||||
// float -> f32
|
||||
Float(FloatTy::F32) => {
|
||||
Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value))
|
||||
}
|
||||
// float -> f64
|
||||
Float(FloatTy::F64) => {
|
||||
Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value))
|
||||
}
|
||||
// float -> float
|
||||
Float(fty) => match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
|
||||
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
},
|
||||
// That's it.
|
||||
_ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -389,12 +389,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let left = left.to_scalar();
|
||||
let right = right.to_scalar();
|
||||
Ok(match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?)
|
||||
}
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
})
|
||||
}
|
||||
_ if left.layout.ty.is_integral() => {
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ where
|
|||
trace!("deref to {} on {:?}", val.layout.ty, *val);
|
||||
|
||||
if val.layout.ty.is_box() {
|
||||
// Derefer should have removed all Box derefs
|
||||
bug!("dereferencing {}", val.layout.ty);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,14 +359,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Ok(Some(match ty.kind() {
|
||||
ty::Ref(_, ty, _) => *ty,
|
||||
ty::RawPtr(mt) => mt.ty,
|
||||
// We should only accept `Box` with the default allocator.
|
||||
// It's hard to test for that though so we accept every 1-ZST allocator.
|
||||
ty::Adt(def, args)
|
||||
if def.is_box()
|
||||
&& self.layout_of(args[1].expect_ty()).is_ok_and(|l| l.is_1zst()) =>
|
||||
{
|
||||
args[0].expect_ty()
|
||||
}
|
||||
// We only accept `Box` with the default allocator.
|
||||
_ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
|
||||
_ => return Ok(None),
|
||||
}))
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ where
|
|||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
|
||||
type BreakTy = FoundParam;
|
||||
type Result = ControlFlow<FoundParam>;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
if !ty.has_param() {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
|
||||
_ => c.super_visit_with(self),
|
||||
|
|
|
|||
|
|
@ -148,14 +148,6 @@ impl CtfeValidationMode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn may_contain_mutable_ref(self) -> bool {
|
||||
match self {
|
||||
CtfeValidationMode::Static { mutbl } => mutbl == Mutability::Mut,
|
||||
CtfeValidationMode::Promoted { .. } => false,
|
||||
CtfeValidationMode::Const { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State for tracking recursive validation of references
|
||||
|
|
@ -511,20 +503,19 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
|||
// If this allocation has size zero, there is no actual mutability here.
|
||||
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
|
||||
if size != Size::ZERO {
|
||||
// Mutable pointer to immutable memory is no good.
|
||||
if ptr_expected_mutbl == Mutability::Mut
|
||||
&& alloc_actual_mutbl == Mutability::Not
|
||||
{
|
||||
throw_validation_failure!(self.path, MutableRefToImmutable);
|
||||
}
|
||||
if ptr_expected_mutbl == Mutability::Mut
|
||||
&& self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref())
|
||||
{
|
||||
throw_validation_failure!(self.path, MutableRefInConstOrStatic);
|
||||
}
|
||||
if alloc_actual_mutbl == Mutability::Mut
|
||||
&& matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
|
||||
{
|
||||
throw_validation_failure!(self.path, ConstRefToMutable);
|
||||
// In a const, everything must be completely immutable.
|
||||
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
|
||||
if ptr_expected_mutbl == Mutability::Mut
|
||||
|| alloc_actual_mutbl == Mutability::Mut
|
||||
{
|
||||
throw_validation_failure!(self.path, ConstRefToMutable);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Potentially skip recursive check.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
|
|||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
|
||||
|
||||
use std::mem;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::ops::{self, NonConstOp, Status};
|
||||
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
||||
|
|
@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) {
|
||||
match t.kind() {
|
||||
ty::FnPtr(_) => ControlFlow::Continue(()),
|
||||
ty::FnPtr(_) => {}
|
||||
ty::Ref(_, _, hir::Mutability::Mut) => {
|
||||
self.checker.check_op(ops::ty::MutRef(self.kind));
|
||||
t.super_visit_with(self)
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess,
|
||||
|
|
@ -556,6 +557,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
|
|||
Status::Unstable(sym::const_mut_refs)
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess,
|
||||
|
|
@ -589,6 +591,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||
let mut err = feature_err(
|
||||
&ccx.tcx.sess,
|
||||
|
|
@ -632,6 +635,7 @@ pub mod ty {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
//! other areas of the compiler as well.
|
||||
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
|
|
@ -33,9 +33,6 @@ pub fn is_equal_up_to_subtyping<'tcx>(
|
|||
/// When validating assignments, the variance should be `Covariant`. When checking
|
||||
/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
|
||||
/// because we want to check for type equality.
|
||||
///
|
||||
/// This mostly ignores opaque types as it can be used in constraining contexts
|
||||
/// while still computing the final underlying type.
|
||||
pub fn relate_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
|
|
@ -47,8 +44,7 @@ pub fn relate_types<'tcx>(
|
|||
return true;
|
||||
}
|
||||
|
||||
let mut builder =
|
||||
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
|
||||
let mut builder = tcx.infer_ctxt().ignoring_regions();
|
||||
let infcx = builder.build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = ObligationCause::dummy();
|
||||
|
|
@ -58,20 +54,5 @@ pub fn relate_types<'tcx>(
|
|||
Ok(()) => {}
|
||||
Err(_) => return false,
|
||||
};
|
||||
let errors = ocx.select_all_or_error();
|
||||
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
|
||||
// we would get unification errors because we're unable to look into opaque types,
|
||||
// even if they're constrained in our current function.
|
||||
for (key, ty) in infcx.take_opaque_types() {
|
||||
let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
|
||||
if hidden_ty != ty.hidden_type.ty {
|
||||
span_bug!(
|
||||
ty.hidden_type.span,
|
||||
"{}, {}",
|
||||
tcx.type_of(key.def_id).instantiate(tcx, key.args),
|
||||
ty.hidden_type.ty
|
||||
);
|
||||
}
|
||||
}
|
||||
errors.is_empty()
|
||||
ocx.select_all_or_error().is_empty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub struct Registry(Arc<RegistryData>);
|
|||
thread_local! {
|
||||
/// The registry associated with the thread.
|
||||
/// This allows the `WorkerLocal` type to clone the registry in its constructor.
|
||||
static REGISTRY: OnceCell<Registry> = OnceCell::new();
|
||||
static REGISTRY: OnceCell<Registry> = const { OnceCell::new() };
|
||||
}
|
||||
|
||||
struct ThreadData {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
|
|||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||
serde_json = "1.0.59"
|
||||
shlex = "1.0"
|
||||
time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] }
|
||||
time = { version = "0.3", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] }
|
||||
tracing = { version = "0.1.35" }
|
||||
# tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
|
||||
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
||||
driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
|
||||
driver_impl_ice_bug_report_outdated =
|
||||
it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the mean time
|
||||
.update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
||||
.url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
|
||||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||
|
||||
driver_impl_ice_flags = compiler flags: {$flags}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
use std::error;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::{env, error, fmt, fs, io};
|
||||
|
||||
use rustc_session::EarlyDiagCtxt;
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
/// Expands argfiles in command line arguments.
|
||||
#[derive(Default)]
|
||||
|
|
@ -86,7 +84,7 @@ impl Expander {
|
|||
fn read_file(path: &str) -> Result<String, Error> {
|
||||
fs::read_to_string(path).map_err(|e| {
|
||||
if e.kind() == io::ErrorKind::InvalidData {
|
||||
Error::Utf8Error(Some(path.to_string()))
|
||||
Error::Utf8Error(path.to_string())
|
||||
} else {
|
||||
Error::IOError(path.to_string(), e)
|
||||
}
|
||||
|
|
@ -94,22 +92,53 @@ impl Expander {
|
|||
}
|
||||
}
|
||||
|
||||
/// Replaces any `@file` arguments with the contents of `file`, with each line of `file` as a
|
||||
/// separate argument.
|
||||
///
|
||||
/// **Note:** This function doesn't interpret argument 0 in any special way.
|
||||
/// If this function is intended to be used with command line arguments,
|
||||
/// `argv[0]` must be removed prior to calling it manually.
|
||||
pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
pub fn arg_expand_all(
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
at_args: &[String],
|
||||
) -> Result<Vec<String>, ErrorGuaranteed> {
|
||||
let mut expander = Expander::default();
|
||||
let mut result = Ok(());
|
||||
for arg in at_args {
|
||||
if let Err(err) = expander.arg(arg) {
|
||||
early_dcx.early_fatal(format!("Failed to load argument file: {err}"));
|
||||
result = Err(early_dcx.early_err(format!("failed to load argument file: {err}")));
|
||||
}
|
||||
}
|
||||
expander.finish()
|
||||
result.map(|()| expander.finish())
|
||||
}
|
||||
|
||||
/// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further
|
||||
/// processing (e.g., without `@file` expansion).
|
||||
///
|
||||
/// This function is identical to [`env::args()`] except that it emits an error when it encounters
|
||||
/// non-Unicode arguments instead of panicking.
|
||||
pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Result<Vec<String>, ErrorGuaranteed> {
|
||||
let mut res = Ok(Vec::new());
|
||||
for (i, arg) in env::args_os().enumerate() {
|
||||
match arg.into_string() {
|
||||
Ok(arg) => {
|
||||
if let Ok(args) = &mut res {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
Err(arg) => {
|
||||
res =
|
||||
Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}")))
|
||||
}
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Utf8Error(Option<String>),
|
||||
enum Error {
|
||||
Utf8Error(String),
|
||||
IOError(String, io::Error),
|
||||
ShellParseError(String),
|
||||
}
|
||||
|
|
@ -117,10 +146,9 @@ pub enum Error {
|
|||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
|
||||
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
|
||||
Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
|
||||
Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"),
|
||||
Error::Utf8Error(path) => write!(fmt, "UTF-8 error in {path}"),
|
||||
Error::IOError(path, err) => write!(fmt, "IO error: {path}: {err}"),
|
||||
Error::ShellParseError(path) => write!(fmt, "invalid shell-style arguments in {path}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
@ -58,7 +59,7 @@ use std::str;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::{Instant, SystemTime};
|
||||
use time::OffsetDateTime;
|
||||
use time::{Date, OffsetDateTime, Time};
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro do_not_use_print($($t:tt)*) {
|
||||
|
|
@ -291,7 +292,7 @@ fn run_compiler(
|
|||
// the compiler with @empty_file as argv[0] and no more arguments.
|
||||
let at_args = at_args.get(1..).unwrap_or_default();
|
||||
|
||||
let args = args::arg_expand_all(&default_early_dcx, at_args);
|
||||
let args = args::arg_expand_all(&default_early_dcx, at_args)?;
|
||||
|
||||
let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) };
|
||||
|
||||
|
|
@ -314,7 +315,7 @@ fn run_compiler(
|
|||
file_loader,
|
||||
locale_resources: DEFAULT_LOCALE_RESOURCES,
|
||||
lint_caps: Default::default(),
|
||||
parse_sess_created: None,
|
||||
psess_created: None,
|
||||
hash_untracked_state: None,
|
||||
register_lints: None,
|
||||
override_queries: None,
|
||||
|
|
@ -768,7 +769,7 @@ fn print_crate_info(
|
|||
}
|
||||
Cfg => {
|
||||
let mut cfgs = sess
|
||||
.parse_sess
|
||||
.psess
|
||||
.config
|
||||
.iter()
|
||||
.filter_map(|&(name, value)| {
|
||||
|
|
@ -1215,12 +1216,10 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
|
|||
|
||||
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
||||
match &sess.io.input {
|
||||
Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
|
||||
Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
|
||||
name.clone(),
|
||||
input.clone(),
|
||||
&sess.parse_sess,
|
||||
),
|
||||
Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.psess),
|
||||
Input::Str { name, input } => {
|
||||
rustc_parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.psess)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1371,6 +1370,9 @@ pub fn install_ice_hook(
|
|||
using_internal_features
|
||||
}
|
||||
|
||||
const DATE_FORMAT: &[time::format_description::FormatItem<'static>] =
|
||||
&time::macros::format_description!("[year]-[month]-[day]");
|
||||
|
||||
/// Prints the ICE message, including query stack, but without backtrace.
|
||||
///
|
||||
/// The message will point the user at `bug_report_url` to report the ICE.
|
||||
|
|
@ -1399,10 +1401,34 @@ fn report_ice(
|
|||
dcx.emit_err(session_diagnostics::Ice);
|
||||
}
|
||||
|
||||
if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
|
||||
use time::ext::NumericalDuration;
|
||||
|
||||
// Try to hint user to update nightly if applicable when reporting an ICE.
|
||||
// Attempt to calculate when current version was released, and add 12 hours
|
||||
// as buffer. If the current version's release timestamp is older than
|
||||
// the system's current time + 24 hours + 12 hours buffer if we're on
|
||||
// nightly.
|
||||
if let Some("nightly") = option_env!("CFG_RELEASE_CHANNEL")
|
||||
&& let Some(version) = option_env!("CFG_VERSION")
|
||||
&& let Some(ver_date_str) = option_env!("CFG_VER_DATE")
|
||||
&& let Ok(ver_date) = Date::parse(&ver_date_str, DATE_FORMAT)
|
||||
&& let ver_datetime = OffsetDateTime::new_utc(ver_date, Time::MIDNIGHT)
|
||||
&& let system_datetime = OffsetDateTime::from(SystemTime::now())
|
||||
&& system_datetime.checked_sub(36.hours()).is_some_and(|d| d > ver_datetime)
|
||||
&& !using_internal_features.load(std::sync::atomic::Ordering::Relaxed)
|
||||
{
|
||||
dcx.emit_note(session_diagnostics::IceBugReportOutdated {
|
||||
version,
|
||||
bug_report_url,
|
||||
note_update: (),
|
||||
note_url: (),
|
||||
});
|
||||
} else {
|
||||
dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
|
||||
} else {
|
||||
dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
}
|
||||
}
|
||||
|
||||
let version = util::version_str!().unwrap_or("unknown_version");
|
||||
|
|
@ -1489,15 +1515,7 @@ pub fn main() -> ! {
|
|||
let mut callbacks = TimePassesCallbacks::default();
|
||||
let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
|
||||
let exit_code = catch_with_exit_code(|| {
|
||||
let args = env::args_os()
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
arg.into_string().unwrap_or_else(|arg| {
|
||||
early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}"))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
RunCompiler::new(&args, &mut callbacks)
|
||||
RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
|
||||
.set_using_internal_features(using_internal_features)
|
||||
.run()
|
||||
});
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
|
|||
ExpandedIdentified => Box::new(AstIdentifiedAnn),
|
||||
ExpandedHygiene => Box::new(AstHygieneAnn { sess }),
|
||||
};
|
||||
let parse = &sess.parse_sess;
|
||||
let psess = &sess.psess;
|
||||
let is_expanded = ppm.needs_ast_map();
|
||||
ex.with_krate(|krate| {
|
||||
pprust_ast::print_crate(
|
||||
|
|
@ -270,8 +270,8 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
|
|||
src,
|
||||
&*annotation,
|
||||
is_expanded,
|
||||
parse.edition,
|
||||
&sess.parse_sess.attr_id_generator,
|
||||
psess.edition,
|
||||
&sess.psess.attr_id_generator,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue