Auto merge of #140607 - lcnr:opaque-type-storage, r= · rust-lang/rust@93308d9 (original) (raw)

``

1

`+

use std::ops::Deref;

`

``

2

+

``

3

`+

use rustc_data_structures::fx::FxIndexMap;

`

1

4

`use rustc_data_structures::undo_log::UndoLogs;

`

2

5

`use rustc_middle::bug;

`

3

6

`use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};

`

4

7

`use tracing::instrument;

`

5

8

``

6

``

`-

use super::OpaqueTypeMap;

`

7

9

`use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};

`

8

10

``

9

11

`#[derive(Default, Debug, Clone)]

`

10

``

`-

pub(crate) struct OpaqueTypeStorage<'tcx> {

`

11

``

`-

/// Opaque types found in explicit return types and their

`

12

``

`-

/// associated fresh inference variable. Writeback resolves these

`

13

``

`-

/// variables to get the concrete type, which can be used to

`

14

``

`-

/// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.

`

15

``

`-

pub opaque_types: OpaqueTypeMap<'tcx>,

`

``

12

`+

pub struct OpaqueTypeStorage<'tcx> {

`

``

13

`+

opaque_types: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,

`

``

14

`+

duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,

`

16

15

`}

`

17

16

``

18

17

`impl<'tcx> OpaqueTypeStorage<'tcx> {

`

`@@ -33,6 +32,52 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {

`

33

32

`}

`

34

33

`}

`

35

34

``

``

35

`+

pub(crate) fn pop_duplicate_entry(&mut self) {

`

``

36

`+

let entry = self.duplicate_entries.pop();

`

``

37

`+

assert!(entry.is_some());

`

``

38

`+

}

`

``

39

+

``

40

`+

pub(crate) fn is_empty(&self) -> bool {

`

``

41

`+

let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;

`

``

42

`+

opaque_types.is_empty() && duplicate_entries.is_empty()

`

``

43

`+

}

`

``

44

+

``

45

`+

pub(crate) fn take_opaque_types(

`

``

46

`+

&mut self,

`

``

47

`+

) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {

`

``

48

`+

let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;

`

``

49

`+

std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))

`

``

50

`+

}

`

``

51

+

``

52

`+

/// Only returns the opaque types from the lookup table. These are used

`

``

53

`+

/// when normalizing opaque types and have a unique key.

`

``

54

`+

///

`

``

55

`` +

/// Outside of canonicalization one should generally use iter_opaque_types

``

``

56

`+

/// to also consider duplicate entries.

`

``

57

`+

pub fn iter_lookup_table(

`

``

58

`+

&self,

`

``

59

`+

) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {

`

``

60

`+

self.opaque_types.iter().map(|(k, v)| (*k, *v))

`

``

61

`+

}

`

``

62

+

``

63

`` +

/// Only returns the opaque types which are stored in duplicate_entries.

``

``

64

`+

///

`

``

65

`+

/// These have to considered when checking all opaque type uses but are e.g.

`

``

66

`+

/// irrelevant for canonical inputs as nested queries never meaningfully

`

``

67

`+

/// accesses them.

`

``

68

`+

pub fn iter_duplicate_entries(

`

``

69

`+

&self,

`

``

70

`+

) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {

`

``

71

`+

self.duplicate_entries.iter().copied()

`

``

72

`+

}

`

``

73

+

``

74

`+

pub fn iter_opaque_types(

`

``

75

`+

&self,

`

``

76

`+

) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {

`

``

77

`+

let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;

`

``

78

`+

opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())

`

``

79

`+

}

`

``

80

+

36

81

`#[inline]

`

37

82

`pub(crate) fn with_log<'a>(

`

38

83

`&'a mut self,

`

`@@ -44,21 +89,27 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {

`

44

89

``

45

90

`impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {

`

46

91

`fn drop(&mut self) {

`

47

``

`-

if !self.opaque_types.is_empty() {

`

``

92

`+

if !self.is_empty() {

`

48

93

` ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));

`

49

94

`}

`

50

95

`}

`

51

96

`}

`

52

97

``

53

``

`-

pub(crate) struct OpaqueTypeTable<'a, 'tcx> {

`

``

98

`+

pub struct OpaqueTypeTable<'a, 'tcx> {

`

54

99

`storage: &'a mut OpaqueTypeStorage<'tcx>,

`

55

100

``

56

101

`undo_log: &'a mut InferCtxtUndoLogs<'tcx>,

`

57

102

`}

`

``

103

`+

impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {

`

``

104

`+

type Target = OpaqueTypeStorage<'tcx>;

`

``

105

`+

fn deref(&self) -> &Self::Target {

`

``

106

`+

self.storage

`

``

107

`+

}

`

``

108

`+

}

`

58

109

``

59

110

`impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {

`

60

111

`#[instrument(skip(self), level = "debug")]

`

61

``

`-

pub(crate) fn register(

`

``

112

`+

pub fn register(

`

62

113

`&mut self,

`

63

114

`key: OpaqueTypeKey<'tcx>,

`

64

115

`hidden_type: OpaqueHiddenType<'tcx>,

`

`@@ -72,4 +123,9 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {

`

72

123

`self.undo_log.push(UndoLog::OpaqueTypes(key, None));

`

73

124

`None

`

74

125

`}

`

``

126

+

``

127

`+

pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {

`

``

128

`+

self.storage.duplicate_entries.push((key, hidden_type));

`

``

129

`+

self.undo_log.push(UndoLog::DuplicateOpaqueType);

`

``

130

`+

}

`

75

131

`}

`