Auto merge of #102026 - Bryanskiy:resolve_update, r=petrochenkov · rust-lang/rust@b8b5cae (original) (raw)

1

1

`//! A pass that checks to make sure private fields and methods aren't used

`

2

2

`//! outside their scopes. This pass will also generate a set of exported items

`

3

3

`//! which are available for use externally when compiled as a library.

`

4

``

`-

use crate::ty::Visibility;

`

``

4

`+

use crate::ty::{DefIdTree, Visibility};

`

5

5

`use rustc_data_structures::fx::FxHashMap;

`

6

6

`use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

`

7

7

`use rustc_macros::HashStable;

`

8

8

`use rustc_query_system::ich::StableHashingContext;

`

9

``

`-

use rustc_span::def_id::LocalDefId;

`

``

9

`+

use rustc_span::def_id::{DefId, LocalDefId};

`

10

10

`use std::hash::Hash;

`

11

11

``

12

12

`/// Represents the levels of accessibility an item can have.

`

`@@ -27,26 +27,36 @@ pub enum AccessLevel {

`

27

27

`Public,

`

28

28

`}

`

29

29

``

30

``

`-

#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Default)]

`

``

30

`+

impl AccessLevel {

`

``

31

`+

pub fn all_levels() -> [AccessLevel; 4] {

`

``

32

`+

[

`

``

33

`+

AccessLevel::Public,

`

``

34

`+

AccessLevel::Exported,

`

``

35

`+

AccessLevel::Reachable,

`

``

36

`+

AccessLevel::ReachableFromImplTrait,

`

``

37

`+

]

`

``

38

`+

}

`

``

39

`+

}

`

``

40

+

``

41

`+

#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]

`

31

42

`pub struct EffectiveVisibility {

`

32

``

`-

public: Option,

`

33

``

`-

exported: Option,

`

34

``

`-

reachable: Option,

`

35

``

`-

reachable_from_impl_trait: Option,

`

``

43

`+

public: Visibility,

`

``

44

`+

exported: Visibility,

`

``

45

`+

reachable: Visibility,

`

``

46

`+

reachable_from_impl_trait: Visibility,

`

36

47

`}

`

37

48

``

38

49

`impl EffectiveVisibility {

`

39

``

`-

pub fn get(&self, tag: AccessLevel) -> Option<&Visibility> {

`

``

50

`+

pub fn get(&self, tag: AccessLevel) -> &Visibility {

`

40

51

`match tag {

`

41

52

`AccessLevel::Public => &self.public,

`

42

53

`AccessLevel::Exported => &self.exported,

`

43

54

`AccessLevel::Reachable => &self.reachable,

`

44

55

`AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait,

`

45

56

`}

`

46

``

`-

.as_ref()

`

47

57

`}

`

48

58

``

49

``

`-

fn get_mut(&mut self, tag: AccessLevel) -> &mut Option {

`

``

59

`+

fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility {

`

50

60

`match tag {

`

51

61

`AccessLevel::Public => &mut self.public,

`

52

62

`AccessLevel::Exported => &mut self.exported,

`

`@@ -56,7 +66,30 @@ impl EffectiveVisibility {

`

56

66

`}

`

57

67

``

58

68

`pub fn is_public_at_level(&self, tag: AccessLevel) -> bool {

`

59

``

`-

self.get(tag).map_or(false, |vis| vis.is_public())

`

``

69

`+

self.get(tag).is_public()

`

``

70

`+

}

`

``

71

+

``

72

`+

fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool {

`

``

73

`+

let mut changed = false;

`

``

74

`+

for level in AccessLevel::all_levels() {

`

``

75

`+

if level <= tag {

`

``

76

`+

let current_effective_vis = self.get_mut(level);

`

``

77

`+

if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) {

`

``

78

`+

changed = true;

`

``

79

`+

*current_effective_vis = vis;

`

``

80

`+

}

`

``

81

`+

}

`

``

82

`+

}

`

``

83

`+

changed

`

``

84

`+

}

`

``

85

+

``

86

`+

fn from_vis(vis: Visibility) -> EffectiveVisibility {

`

``

87

`+

EffectiveVisibility {

`

``

88

`+

public: vis,

`

``

89

`+

exported: vis,

`

``

90

`+

reachable: vis,

`

``

91

`+

reachable_from_impl_trait: vis,

`

``

92

`+

}

`

60

93

`}

`

61

94

`}

`

62

95

``

`@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels {

`

89

122

``

90

123

`pub fn get_access_level(&self, id: Id) -> Option {

`

91

124

`self.get_effective_vis(id).and_then(|effective_vis| {

`

92

``

`-

for level in [

`

93

``

`-

AccessLevel::Public,

`

94

``

`-

AccessLevel::Exported,

`

95

``

`-

AccessLevel::Reachable,

`

96

``

`-

AccessLevel::ReachableFromImplTrait,

`

97

``

`-

] {

`

``

125

`+

for level in AccessLevel::all_levels() {

`

98

126

`if effective_vis.is_public_at_level(level) {

`

99

127

`return Some(level);

`

100

128

`}

`

`@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels {

`

103

131

`})

`

104

132

`}

`

105

133

``

106

``

`-

pub fn set_access_level(&mut self, id: Id, tag: AccessLevel) {

`

107

``

`-

let mut effective_vis = self.get_effective_vis(id).copied().unwrap_or_default();

`

108

``

`-

for level in [

`

109

``

`-

AccessLevel::Public,

`

110

``

`-

AccessLevel::Exported,

`

111

``

`-

AccessLevel::Reachable,

`

112

``

`-

AccessLevel::ReachableFromImplTrait,

`

113

``

`-

] {

`

114

``

`-

if level <= tag {

`

115

``

`-

*effective_vis.get_mut(level) = Some(Visibility::Public);

`

116

``

`-

}

`

117

``

`-

}

`

118

``

`-

self.map.insert(id, effective_vis);

`

119

``

`-

}

`

120

``

-

121

134

`pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {

`

122

135

`self.map.get(&id)

`

123

136

`}

`

`@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels {

`

129

142

`pub fn map_id<OutId: Hash + Eq + Copy>(&self, f: impl Fn(Id) -> OutId) -> AccessLevels {

`

130

143

`AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }

`

131

144

`}

`

``

145

+

``

146

`+

pub fn set_access_level(

`

``

147

`+

&mut self,

`

``

148

`+

id: Id,

`

``

149

`+

default_vis: impl FnOnce() -> Visibility,

`

``

150

`+

tag: AccessLevel,

`

``

151

`+

) {

`

``

152

`+

let mut effective_vis = self

`

``

153

`+

.get_effective_vis(id)

`

``

154

`+

.copied()

`

``

155

`+

.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));

`

``

156

`+

for level in AccessLevel::all_levels() {

`

``

157

`+

if level <= tag {

`

``

158

`+

*effective_vis.get_mut(level) = Visibility::Public;

`

``

159

`+

}

`

``

160

`+

}

`

``

161

`+

self.map.insert(id, effective_vis);

`

``

162

`+

}

`

``

163

`+

}

`

``

164

+

``

165

`+

impl<Id: Hash + Eq + Copy + Into> AccessLevels {

`

``

166

`` +

// parent_id is not necessarily a parent in source code tree,

``

``

167

`+

// it is the node from which the maximum effective visibility is inherited.

`

``

168

`+

pub fn update(

`

``

169

`+

&mut self,

`

``

170

`+

id: Id,

`

``

171

`+

nominal_vis: Visibility,

`

``

172

`+

default_vis: impl FnOnce() -> Visibility,

`

``

173

`+

parent_id: Id,

`

``

174

`+

tag: AccessLevel,

`

``

175

`+

tree: impl DefIdTree,

`

``

176

`+

) -> Result<bool, ()> {

`

``

177

`+

let mut changed = false;

`

``

178

`+

let mut current_effective_vis = self

`

``

179

`+

.get_effective_vis(id)

`

``

180

`+

.copied()

`

``

181

`+

.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));

`

``

182

`+

if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) {

`

``

183

`+

for level in AccessLevel::all_levels() {

`

``

184

`+

if tag >= level {

`

``

185

`+

let inherited_effective_vis_at_level = *inherited_effective_vis.get(level);

`

``

186

`+

let calculated_effective_vis =

`

``

187

`+

if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {

`

``

188

`+

inherited_effective_vis_at_level

`

``

189

`+

} else {

`

``

190

`+

nominal_vis

`

``

191

`+

};

`

``

192

`+

changed |= current_effective_vis.update(calculated_effective_vis, level, tree);

`

``

193

`+

}

`

``

194

`+

}

`

``

195

`+

} else {

`

``

196

`+

if !id.into().is_crate_root() {

`

``

197

`+

return Err(());

`

``

198

`+

}

`

``

199

`+

changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree);

`

``

200

`+

}

`

``

201

`+

self.map.insert(id, current_effective_vis);

`

``

202

`+

Ok(changed)

`

``

203

`+

}

`

132

204

`}

`

133

205

``

134

206

`impl Default for AccessLevels {

`